Reputation: 516
In my component, I render this textarea:
<textarea id="descript" rows="8" value={this.state.description} />
and I was surprised to find that I couldn't type in it. After some experimentation, I found that I was typing it in, but react was just reseting the value every time I typed a character to the state variable. So, I've gotten it to let me type by adding this onChange:
<textarea id="descript" rows="8" value={this.state.description}
onChange={() => {this.textChanged();}} />
and this is the handler:
textChanged(event) {
var newDesc = document.getElementById('descript').value;
this.setState({'description':newDesc});
}
This works, but it's an incredibly expensive way to have React not do anything. Is there a better/right way to approach this that will just let me edit the textarea? For example, with the input fields in the form, I just use defaultValue instead, but I need this one to be multiple lines.
Upvotes: 2
Views: 4537
Reputation: 152
In React, this is called a controlled-component. Since you're setting your <textarea>
's value to this.state.description
, the <textarea>
will always reflect this, making the React state the source of truth. As a result you must also handle changes. You may be falling victim to premature optimization, this is generally very fast, and is a best practice. In React, your component rendering should be predicable based on your state and props.
As Arslan mentioned, however, since your handler receives event
just the same as a normal onChange
handler, a simpler way to do this is simply to set your state to event.target.value
rather than grabbing a reference to your <textarea>
and getting it's value.
Upvotes: 3
Reputation: 2528
The way you are trying is okay. Just need a little tweak. Try this:
<textarea
id="descript"
rows="8"
value={this.state.description}
onChange={this.textChanged}
/>
textChanged(event) {
this.setState({
description: event.target.value
});
}
And don't forget to bind the function in your constructor like this:
this.textChanged= this.textChanged.bind(this);
As you are using it as a controlled component so the state will always be reflected in the textarea's value.
Upvotes: 6
Reputation: 11
You are using the as a controlled component, where the value it holds will always be this.state.description. You are right that when used this way you will need supply an onChange function but you do not need to set an id and use the document API.
You can read more about it here: https://reactjs.org/docs/forms.html#controlled-components
You do not need to use it as a controlled component. If you don't set the value prop you will be able to type as is. Then when you wish to capture that value you can read the value from the textarea element either by ref or by id.
Upvotes: 1
Reputation: 1288
Is there a reason why the textarea
contents need to be in the state
?
You can use another variable (or a property passed into the component) instead:
<textarea id="descript" rows="8" value={description} />
or
<textarea id="descript" rows="8" value={this.props.description} />
Then instead of an onChange
handler, you read the updated value of the textarea
when you are ready to use it.
Upvotes: 1