How to set defaultValue, value={this.props.value}, and update the value of a text input with React?
For forms in React:
The defaultValue and defaultChecked props are only used during initial render. If you need to update the value in a subsequent render, you will need to use a controlled component.
Docs on controlled components
so, whenever you want to edit props, you have to set them in the local component state ( like you did in the getInitialState by setting value to the props ). Props are immutable, so setting the value or defaultValue of the input to the prop will/should not allow you to change the prop.
So below, what I have done is set value of the input to this.state.name, and this.state.name is set to this.props.name on initial state and whenever you call update, it will update the components state with whatever is typed in the input.
if you need to pass the name back to a parent component, then you need to pass in a function from the parent which you can then call from the child to inform the parent that the name value has changed, parent will then need to update the name which then gets passed back down to the child...this creates a 2 way data binding..
// Allows a user to edit a blog entry.
var EditBlog = React.createClass({
displayName: 'Editor',
propTypes: {
name: React.PropTypes.string.isRequired
},
getInitialState: function() {
console.log("getInitialState value: " + this.props.name);
return {
value: this.props.name,
};
},
componentWillReceiveProps: function ( newProps ) {
this.setState( { value:newProps.name } );
}
handleChange: function(event) {
console.log("changing the text area to: " + event.target.value)
this.setState({value: event.target.value});
},
updateBlogText: function() {
ajax('update_blog.php', { blogtext: this.value, username: this.props.username }, function(response) {
console.log("Updating blog text to: " + this.state.value + " with user: " + this.props.username);
if (response.result === 'success') {
console.log("Success!");
//this.props.setClicks(response.counter, response.username, response.blogtext);
//this.props.setUsername(response.username);
//this.props.setBlog(response.blogtext);
}
else if (response.result === 'error') {
alert('Error: ' + response.msg);
console.log("Error!");
}
else {
alert('Response message has no result attribute.');
}
}.bind(this));
console.log("Click button clicked");
},
render: function() {
console.log("this.state.value: " + this.state.value)
console.log("this.state.value blogtext: " + this.props.name);
this.state.value = this.props.value;
return (
<div>
<h2>Blog Entry</h2>
<center>
<form id="noter-save-form" method="POST">
<textarea id="noter-text-area" name="textarea" onChange={this.handleChange} value={value}></textarea>
<input type="submit" value="Save" onClick={this.updateBlogText}/>
</form>
</center>
</div>
);
}
});
Reading your code, there is no need to:
componentDidMount: function() {
this.setState({value: this.props.name});
},
The job is already done by getInitialState
. If you intend to have the state updated when the component receive new props you should write:
componentWillReceiveProps: function(nextProps) {
this.setState({value: nextProps.name});
},
I think that, in your case, you should use this.state.value
and that it is not well initialized because componentWillReceiveProps
was no implemented to update the component state when receiving a props.name
value different from undefined
.