Search code examples
javascriptreactjs

A component is changing an uncontrolled input of type text to be controlled error in ReactJS


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>
  )
}

Solution

  • 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 || '') = ''