Un componente sta modificando un input non controllato di testo di tipo per controllare l'errore in ReactJS


331

Avvertenza: un componente sta modificando un input non controllato di tipo testo da controllare. Gli elementi di input non devono passare da incontrollati a controllati (o viceversa). Decidi se utilizzare un elemento di input controllato o non controllato per la durata del componente. *

Di seguito è riportato il mio codice:

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

2
qual è il valore iniziale di fieldsin state?
Mayank Shukla,

2
costruttore (oggetti di scena) {super (oggetti di scena); this.state = {fields: {}, errori: {}} this.onSubmit = this.onSubmit.bind (this); }
Riya Kapuria,

Risposte:


651

Il motivo è, nello stato definito:

this.state = { fields: {} }

campi come oggetto vuoto, quindi durante il primo rendering this.state.fields.namesarà undefined, e il campo di input otterrà il suo valore come:

value={undefined}

Per questo motivo, il campo di input non sarà controllato.

Dopo aver inserito qualsiasi valore in input, fieldsnello stato viene modificato in:

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

E in quel momento il campo di input viene convertito in un componente controllato; ecco perché stai ricevendo l'errore:

Un componente sta modificando un input non controllato di tipo testo da controllare.

Possibili soluzioni:

1- Definire lo fieldsstato in come:

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

2- Oppure definire la proprietà del valore usando la valutazione Cortocircuito in questo modo:

value={this.state.fields.name || ''}   // (undefined || '') = ''

5
c'è un motivo indefinito è "incontrollato" mentre quest'ultimo è "controllato" - cosa significano?
Prashanth Subramanian

2
perché ''è un valore stringa valido. quindi quando si cambia ''in 'xyz', il tipo di input non cambia significa controllato a controllato. Ma in caso di undefineddi xyztipo cambierà da incontrollata a controllata.
Mayank Shukla,

1
Grazie per questo ha funzionato per me:value={this.state.fields.name || ''}
Bob

1
Non sapevo che una volta indefinito il valore, l'input diventava automaticamente incontrollato, ottimo. Ho già risolto il mio problema
Adrian Serna il

1
sorprendente! perché non l'ho visto menzionato nei documenti ufficiali o sono cieco? link alla fonte per favore :)
Dheeraj

34

Passare valuea defaultValuerisolverlo.

Nota :

defaultValueè solo per il carico iniziale. Se si desidera inizializzare, inputè necessario utilizzare defaultValue, ma se si desidera utilizzare stateper modificare il valore, è necessario utilizzare value. Leggi questo per di più.

Ho usato value={this.state.input ||""}a inputsbarazzarsi di tale avviso.


2
Grazie! Mi sono imbattuto in questo problema e le altre soluzioni non si applicavano a me, ma questa soluzione ha aiutato.
PepperAddict,

14

All'interno del componente mettere la casella di input nel modo seguente.

<input className="class-name"
              type= "text"
              id="id-123"
              value={ this.state.value || "" }
              name="field-name"
              placeholder="Enter Name"
              />

13

SEMPLICEMENTE, devi prima impostare lo stato iniziale

Se non si imposta lo stato iniziale, la reazione lo tratterà come un componente non controllato


10

Oltre alla risposta accettata, se stai usando un inputtipo checkboxo radio, ho scoperto che ho bisogno di null / indefinito controllare anche l' checkedattributo.

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

E se stai usando TS (o Babel), potresti usare la coalescenza nullish invece dell'operatore logico OR:

value={myStateValue ?? ''}
checked={someBoolean ?? false}

8

Imposta prima lo stato corrente ...this.state

È perché quando si intende assegnare un nuovo stato potrebbe non essere definito. quindi verrà risolto impostando lo stato estraendo anche lo stato corrente

this.setState({...this.state, field})

Se nel tuo stato è presente un oggetto, devi impostare lo stato come segue, supponendo di dover impostare il nome utente all'interno dell'oggetto utente.

this.setState({user:{...this.state.user, ['username']: username}})

1
A quanto ho capito, setState ha già la precedenza solo sui campi, quindi nel primo caso non dovrebbe essere necessario destrutturare l'assegnazione. Nel secondo stato potrebbe essere necessario poiché setState sostituirà un oggetto secondario all'ingrosso.
Kzqai,

6
const [name, setName] = useState()

genera errore non appena si digita nel campo di testo

const [name, setName] = useState('') // <-- by putting in quotes 

risolverà il problema in questo esempio di stringa.


2

Se si utilizzano più input nel campo on, seguire: Ad esempio:

class AddUser extends React.Component {
   constructor(props){
     super(props);

     this.state = {
       fields: { UserName: '', Password: '' }
     };
   }

   onChangeField = event => {
    let name = event.target.name;
    let value = event.target.value;
    this.setState(prevState => {
        prevState.fields[name] =  value;
        return {
           fields: prevState.fields
        };
    });
  };

  render() { 
     const { UserName, Password } = this.state.fields;
     return (
         <form>
             <div>
                 <label htmlFor="UserName">UserName</label>
                 <input type="text" 
                        id='UserName' 
                        name='UserName'
                        value={UserName}
                        onChange={this.onChangeField}/>
              </div>
              <div>
                  <label htmlFor="Password">Password</label>
                  <input type="password" 
                         id='Password' 
                         name='Password'
                         value={Password}
                         onChange={this.onChangeField}/>
              </div>
         </form>
     ); 
  }
}

Cerca il tuo problema su:

onChangeField = event => {
    let name = event.target.name;
    let value = event.target.value;
    this.setState(prevState => {
        prevState.fields[name] =  value;
        return {
            fields: prevState.fields
        };
    });
};

1

Utilizzando React Hooks, inoltre, non dimenticare di impostare il valore iniziale.
Stavo usando <input type='datetime-local' value={eventStart} />e iniziale eventStartera come

const [eventStart, setEventStart] = useState();
invece
const [eventStart, setEventStart] = useState('');.

La stringa vuota tra parentesi è la differenza.
Inoltre, se si reimposta il modulo dopo l'invio come faccio, è necessario impostarlo nuovamente su stringa vuota, non solo su parentesi vuote.

Questo è solo il mio piccolo contributo a questo argomento, forse aiuterà qualcuno.


0

Nel mio caso è stato praticamente quello che dice la risposta principale di Mayank Shukla. L'unico dettaglio era che al mio stato mancava completamente la proprietà che stavo definendo.

Ad esempio, se si dispone di questo stato:

state = {
    "a" : "A",
    "b" : "B",
}

Se stai espandendo il tuo codice, potresti voler aggiungere un nuovo prop così, in qualche altro punto del tuo codice potresti creare una nuova proprietà il ccui valore non è solo non definito sullo stato del componente ma la proprietà stessa non è definita.

Per risolvere questo problema, assicurati di aggiungere cnel tuo stato e dargli un valore iniziale adeguato.

per esempio,

state = {
    "a" : "A",
    "b" : "B",
    "c" : "C", // added and initialized property!
}

Spero di essere stato in grado di spiegare il mio caso limite.


0

Ricevo lo stesso avvertimento: un componente sta modificando un input non controllato di tipo nascosto da controllare. Non riesco a risolvere il mio problema. Qualche idea sul perché?

export default ({  valueName, onChangeAllg,}) => {

          <TextField
            id={"name"}
            select
            label={"name"}
            value={valueName.geschlecht || ""}
            name={"name"}
            onChange={onChangeAllg}

          >
            {nameList.map((option) => (
              <MenuItem key={option.value} value={option.value}>
                {option.label}
              </MenuItem>
            ))}
          </TextField>

ho provato ({ valueName, valueName: {geschlecht=""}, onChangeAllg,})evalue={valueName.geschlecht || ""}


l'ho trovato. defaultValue={""}Mancava un interno del TextField
Dr. Malte Westerloh,

0

Avvertenza: un componente sta modificando un input non controllato di tipo testo da controllare. Gli elementi di input non devono passare da incontrollati a controllati (o viceversa). Decidi se utilizzare un elemento di input controllato o non controllato per la durata del componente.

Soluzione: verificare se il valore non è indefinito

React / Formik / Bootstrap / TypeScript

esempio :

{ values?.purchaseObligation.remainingYear ?
  <Input
   tag={Field}
   name="purchaseObligation.remainingYear"
   type="text"
   component="input"
  /> : null
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.