Reputation: 2036
I am trying to figure this out, I don't know why this isn't working
<input type="text" id="first_name" name="first_name" className="form-control" defaultValue={this.props.user.first_name} required/>
but this works
<input type="text" id="first_name" name="first_name" className="form-control" value={this.props.user.first_name} required/>
the difference is value
and defaultValue
, if I use value the field becomes readonly and using defaultValue doesn't print any thing.
I am using react with meteor. I have tried logging this.props.user
in render method before the return
statement and it prints the object.
Upvotes: 0
Views: 299
Reputation: 2605
When you assign this.props.user.first_name
to the value
attribute it's not that the input field is becoming read-only, it's that you are never handling what happens when that value changes. React is simply re-rendering it with the value you directly assigned to it each time.
If you are looking to make the field editable + have the default user name value you should probably maintain and be aware of the state of the input.
So for example:
// Initialize some component state in either your constructor or getInitialState function
constructor(props){
super(props);
this.state = {userInput: this.props.user.first_name};
}
// Have a function that updates state when your input changes
onInputChange(event) {
this.setState({ userInput: event.target.value });
}
// Then set the value equal to your userInput state and add an onChange
// prop to the input tag in your render method.
render() {
return (
...
<input
type="text"
id="first_name"
name="first_name"
className="form-control"
value={this.state.userInput}
onChange={this.onInputChange.bind(this)} />
)
}
Then the value for the field initializes to the value it's being provided through this.props.user.first_name
, while also remaining editable.
Edit:
As pointed out in the comments, while valid, this is actually an anti-pattern in React. Because the initial state of the child component is only called once, a change from a parent to the prop value of this.props.user.first_name
will not cause any change in the state of the child. This is fine if the use case is to expressly set an initial value that you do not want or expect to change during the component life-cycle (though even then it's not a great pattern), but if you do expect the initial value to be mutable you have two options.
Option One: Bring the state up into the parent component, where it likely belongs. The child component should then receive and render any props that are sent it's way. Changes to the initial value are handled in the parent component state, props are treated as immutable, and everything stays in sync.
Option Two: If for whatever reason you both need to determine state from props and you also expect those props to change, you can make use of the componentWillReceiveProps(nextProps)
life-cycle method to keep everything in sync. This will allow you to check this.props
against nextProps
and make any state changes if they are necessary:
componentWillReceiveProps(nextProps) {
if(nextProps.user.first_name !== this.props.user.first_name){
this.setState({
userInput: nextProps.user.first_name
});
}
}
Here's a link to the DOCS for further reference.
Upvotes: 1