I have a textarea where I want to have an onChange event. When text is entered, I want to compute the length of the string entered and then pass it to another react component to display the character count. However, I’m having trouble passing the data into my react component.
I have 3 react components in total:
- SegmentCalculator: this is my full app
- InputBox: this is where a user would enter their string
- CharacterBox: this is where I’d like to display my character count
Here’s what I have so far:
class InputBox extends React.Component { constructor(props) { super(props); this.state = { value: null, } } render() { return ( <label> Input: <textarea type="text" value={this.state.value} onChange={() => this.props.onChange(this.state.value)} /> </label> ); } } class CharacterBox extends React.Component { render() { return ( <div>Character Count:{this.props.charCount}</div> ) } } class SegmentCalculator extends React.Component { constructor(props) { super(props); this.state = { inputChars: null, }; } handleChange(value) { this.setState({ inputChars: value, inputCharsLength: value.length, }); } render() { let charaterCount = this.state.inputCharsLength; return ( <div className="segment-calculator"> <div className="input-box"> <InputBox onChange={() => this.handleChange()} /> </div> <div className="characters"> <CharacterBox charCount={charaterCount}/> </div> </div> ); } }
Advertisement
Answer
You have a semi-controlled input, meaning, it has local state but you don’t update it.
Pass the input state from the parent.
InputBox – Pass the value
prop through to the textarea
element. Pass the onChange
event’s target value to the onChange
callback prop.
class InputBox extends React.Component { render() { return ( <label> Input: <textarea type="text" value={this.props.value} onChange={(e) => this.props.onChange(e.target.value)} /> </label> ); } }
SegmentCalculator – Pass this.state.inputChars
to the InputBox
value
prop. The input length is derived state so there is no reason to store it in state.
class SegmentCalculator extends React.Component { constructor(props) { super(props); this.state = { inputChars:'', }; } handleChange = (value) => { this.setState({ inputChars: value, }); } render() { const { inputChars } = this.state; return ( <div className="segment-calculator"> <div className="input-box"> <InputBox onChange={this.handleChange} value={inputChars} /> </div> <div className="characters"> <CharacterBox charCount={inputChars.length}/> </div> </div> ); } }
class InputBox extends React.Component { render() { return ( <label> Input: <textarea type="text" value={this.props.value} onChange={(e) => this.props.onChange(e.target.value)} /> </label> ); } } class CharacterBox extends React.Component { render() { return ( <div>Character Count:{this.props.charCount}</div> ) } } class SegmentCalculator extends React.Component { constructor(props) { super(props); this.state = { inputChars: '', }; } handleChange = (value) => { this.setState({ inputChars: value, }); } render() { const { inputChars } = this.state; return ( <div className="segment-calculator"> <div className="input-box"> <InputBox onChange={this.handleChange} value={inputChars} /> </div> <div className="characters"> <CharacterBox charCount={inputChars.length}/> </div> </div> ); } } const rootElement = document.getElementById("root"); ReactDOM.render( <SegmentCalculator />, rootElement );
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script> <div id="root" />