Warning: A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.*
Following is my code:
constructor(props) {
super(props);
this.state = {
fields: {},
errors: {}
}
this.onSubmit = this.onSubmit.bind(this);
}
....
onChange(field, e){
let fields = this.state.fields;
fields[field] = e.target.value;
this.setState({fields});
}
....
render() {
return(
<div className="form-group">
<input
value={this.state.fields["name"]}
onChange={this.onChange.bind(this, "name")}
className="form-control"
type="text"
refs="name"
placeholder="Name *"
/>
<span style={{color: "red"}}>{this.state.errors["name"]}</span>
</div>
)
}
The reason is, in state you defined:
this.state = { fields: {} }
fields as a blank object, so during the first rendering this.state.fields.name will be undefined, and the input field will get its value as:
value={undefined}
Because of that, the input field will become uncontrolled.
Once you enter any value in input, fields in state gets changed to:
this.state = { fields: {name: 'xyz'} }
And at that time the input field gets converted into a controlled component; that's why you are getting the error:
A component is changing an uncontrolled input of type text to be controlled.
Possible Solutions:
1- Define the fields in state as:
this.state = { fields: {name: ''} }
2- Or define the value property by using Short-circuit evaluation like this:
value={this.state.fields.name || ''} // (undefined || '') = ''
Changing value to defaultValue will resolve it.
Note:
defaultValueis only for the initial load. If you want to initialize theinputthen you should usedefaultValue, but if you want to usestateto change the value then you need to usevalue. Read this for more.
I used value={this.state.input ||""} in input to get rid of that warning.
Inside the component put the input box in the following way.
<input className="class-name"
type= "text"
id="id-123"
value={ this.state.value || "" }
name="field-name"
placeholder="Enter Name"
/>