Un componente está cambiando una entrada no controlada de tipo texto para controlar el error en ReactJS

Resuelto Riya Kapuria asked hace 7 años • 28 respuestas

Advertencia: Un componente está cambiando una entrada no controlada de tipo texto para controlarla. Los elementos de entrada no deben pasar de no controlados a controlados (o viceversa). Decida entre utilizar un elemento de entrada controlado o no controlado durante la vida útil del componente.*

El siguiente es mi código:

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>
  )
}
Riya Kapuria avatar Oct 30 '17 16:10 Riya Kapuria
Aceptado

El motivo es que, en el estado que definiste:

this.state = { fields: {} }

campos como un objeto en blanco, por lo que durante la primera representación this.state.fields.nameserá undefinedy el campo de entrada obtendrá su valor como:

value={undefined}

Debido a eso, el campo de entrada quedará descontrolado.

Una vez que ingresa cualquier valor en la entrada, fieldsel estado cambia a:

this.state = { fields: {name: 'xyz'} }

Y en ese momento el campo de entrada se convierte en un componente controlado; por eso te sale el error:

Un componente está cambiando una entrada no controlada de tipo texto para que sea controlada.

Soluciones posibles:

1- Defina el fieldsestado en como:

this.state = { fields: {name: ''} }

2- O defina la propiedad de valor utilizando una evaluación de cortocircuito como esta:

value={this.state.fields.name || ''}   // (undefined || '') = ''
Mayank Shukla avatar Oct 30 '2017 09:10 Mayank Shukla

Cambiar valuea defaultValuelo resolverá.

Nota :

defaultValuees sólo para la carga inicial. Si desea inicializar el inputentonces debe usar defaultValue, pero si desea usarlo statepara cambiar el valor entonces debe usar value. Lea esto para obtener más información.

Solía value={this.state.input ||""}​​​​deshacerme inputde esa advertencia.

MoFoLuWaSo avatar Oct 07 '2019 12:10 MoFoLuWaSo

Dentro del componente coloque el cuadro de entrada de la siguiente manera.

<input
    className="class-name"
    type= "text"
    id="id-123"
    value={ this.state.value || "" }
    name="field-name"
    placeholder="Enter Name"
/>
Tabish avatar Nov 12 '2019 09:11 Tabish

Además de la respuesta aceptada, si está utilizando un inputtipo de checkboxo radio, descubrí que checkedtambién necesito verificar el atributo como nulo/indefinido.

<input
  id={myId}
  name={myName}
  type="checkbox" // or "radio"
  value={myStateValue || ''}
  checked={someBoolean ? someBoolean : false}
  />

Y si está utilizando TS (o Babel), puede utilizar la fusión nula en lugar del operador lógico OR:

value={myStateValue ?? ''}
checked={someBoolean ?? false}
Lynden Noye avatar Jan 18 '2020 08:01 Lynden Noye