Eine Komponente ändert eine unkontrollierte Eingabe vom Typ Text, um Fehler in ReactJS zu steuern

329

Warnung: Eine Komponente ändert eine unkontrollierte Eingabe des zu steuernden Texttyps. Eingangselemente sollten nicht von unkontrolliert zu kontrolliert (oder umgekehrt) wechseln. Entscheiden Sie sich für die Lebensdauer der Komponente zwischen der Verwendung eines gesteuerten oder unkontrollierten Eingabeelements. *

Folgendes ist mein 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>
  )
}
Riya Kapuria
quelle
1
Was ist der Anfangswert von fieldsin state?
Mayank Shukla
2
Konstruktor (Requisiten) {Super (Requisiten); this.state = {Felder: {}, Fehler: {}} this.onSubmit = this.onSubmit.bind (this); }
Riya Kapuria
2
Mögliches Duplikat von React - Ändern einer unkontrollierten Eingabe
Michael Freidgeim

Antworten:

645

Der Grund ist in dem von Ihnen definierten Zustand:

this.state = { fields: {} }

Felder als leeres Objekt, so dass während des ersten Rendering this.state.fields.namewerden undefined, und das Eingabefeld seinen Wert erhalten als:

value={undefined}

Dadurch wird das Eingabefeld unkontrolliert.

Sobald Sie einen Wert in die Eingabe eingegeben haben, wird der fieldsStatus in geändert in:

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

Zu diesem Zeitpunkt wird das Eingabefeld in eine gesteuerte Komponente umgewandelt. Deshalb erhalten Sie den Fehler:

Eine Komponente ändert eine unkontrollierte Eingabe des zu steuernden Texttyps.

Mögliche Lösungen:

1- Definieren Sie den fieldsStatus in als:

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

2- Oder definieren Sie die Werteigenschaft mithilfe der folgenden Kurzschlussauswertung :

value={this.state.fields.name || ''}   // (undefined || '') = ''
Mayank Shukla
quelle
3
Gibt es einen Grund, warum undefiniert "unkontrolliert" ist, während letzterer "kontrolliert" ist - was bedeuten diese?
Prashanth Subramanian
@PrashanthSubramanian Vielleicht könnte dies helfen, es besser zu verstehen. reactjs.org/docs/forms.html#controlled-components
rotimi-best
Ich habe während des Änderungsereignisses keine undefinierten in meinem Zustand
Alexey Sh.
2
weil ''ist ein gültiger Zeichenfolgenwert. Wenn Sie also ''zu 'xyz' wechseln, ändert der Eingabetyp nicht die Mittel, die gesteuert zu gesteuert werden. Im Falle von undefinedto wechselt der xyzTyp jedoch von unkontrolliert zu kontrolliert.
Mayank Shukla
1
tolle! weil ich das nicht in den offiziellen Dokumenten erwähnt habe, oder bin ich blind? Link zur Quelle bitte :)
Dheeraj
34

Durch Ändern valuein defaultValuewird das Problem behoben.

Hinweis :

defaultValueist nur für die anfängliche Belastung. Wenn Sie das initialisieren möchten, inputsollten Sie verwenden defaultValue, aber wenn Sie stateden Wert ändern möchten, müssen Sie verwenden value. Lesen Sie dies für mehr.

Früher habe ich value={this.state.input ||""}in inputdieser Warnung loszuwerden.

MoFoLuWaSo
quelle
2
Vielen Dank! Ich bin auf dieses Problem gestoßen und die anderen Lösungen haben sich nicht auf mich ausgewirkt, aber diese Lösung hat geholfen.
PepperAddict
14

Fügen Sie innerhalb der Komponente das Eingabefeld folgendermaßen ein.

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

EINFACH müssen Sie zuerst den Anfangszustand einstellen

Wenn Sie den Anfangszustand nicht festlegen, wird durch Reagieren eine unkontrollierte Komponente behandelt

Vaibhav Bacchav
quelle
10

Zusätzlich zur akzeptierten Antwort muss das Attribut auch null / undefiniert überprüft werden , wenn Sie einen inputTyp checkboxoder verwenden .radiochecked

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

Und wenn Sie TS (oder Babel) verwenden, können Sie anstelle des logischen ODER-Operators nullish coalescing verwenden:

value={myStateValue ?? ''}
checked={someBoolean ?? false}
Lynden Noye
quelle
8

Stellen Sie zuerst den aktuellen Status ein ...this.state

Dies liegt daran, dass ein neuer Status möglicherweise nicht definiert ist, wenn Sie ihn zuweisen. Daher wird dies behoben, indem der Status so eingestellt wird, dass auch der aktuelle Status extrahiert wird

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

Wenn sich in Ihrem Status ein Objekt befindet, sollten Sie den Status wie folgt festlegen. Angenommen, Sie müssen den Benutzernamen im Benutzerobjekt festlegen.

this.setState({user:{...this.state.user, ['username']: username}})
NuOne
quelle
1
Soweit ich weiß, überschreibt setState bereits nur Felder, sodass es im ersten Fall unnötig sein sollte, die Zuweisung zu zerstören. Im zweiten Zustand kann dies erforderlich sein, da setState einen Unterobjekt-Großhandel ersetzt.
Kzqai
6
const [name, setName] = useState()

generiert einen Fehler, sobald Sie das Textfeld eingeben

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

behebt das Problem in diesem Zeichenfolgenbeispiel.

Nelles
quelle
2

Wenn Sie mehrere Eingaben in ein Feld verwenden, gehen Sie wie folgt vor: Zum Beispiel:

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

Suchen Sie Ihr Problem unter:

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

Vergessen Sie bei der Verwendung von React Hooks auch nicht, den Anfangswert festzulegen.
Ich benutzte <input type='datetime-local' value={eventStart} />und Initiale eventStartwar wie

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

Die leere Zeichenfolge in Klammern ist ein Unterschied.
Wenn Sie das Formular nach dem Senden zurücksetzen, wie ich es tue, müssen Sie es erneut auf eine leere Zeichenfolge setzen, nicht nur auf leere Klammern.

Dies ist nur mein kleiner Beitrag zu diesem Thema, vielleicht hilft es jemandem.

Zrna
quelle
0

In meinem Fall war es so ziemlich das, was Mayank Shuklas Top-Antwort sagt. Das einzige Detail war, dass meinem Staat die von mir definierte Eigenschaft völlig fehlte.

Wenn Sie beispielsweise diesen Status haben:

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

Wenn Sie Ihren Code erweitern, möchten Sie möglicherweise eine neue Requisite hinzufügen, sodass Sie an einer anderen Stelle in Ihrem Code möglicherweise eine neue Eigenschaft erstellen, cderen Wert nicht nur für den Status der Komponente undefiniert ist, sondern die Eigenschaft selbst nicht definiert ist.

Um dies zu lösen, fügen cSie einfach Ihren Status hinzu und geben Sie ihm einen geeigneten Anfangswert.

z.B,

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

Ich hoffe, ich konnte meinen Randfall erklären.

Daniel Segura
quelle
0

Ich erhalte die gleiche Warnung: Eine Komponente ändert eine unkontrollierte Eingabe vom Typ versteckt, um gesteuert zu werden. Ich kann mein Problem nicht beheben. Irgendwelche Ideen warum?

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>

Ich habe es versucht ({ valueName, valueName: {geschlecht=""}, onChangeAllg,})undvalue={valueName.geschlecht || ""}

Dr. Malte Westerloh
quelle
ich habe es gefunden. Ein defaultValue={""}Inneres des TextFields fehlte
Dr. Malte Westerloh
0

Warnung: Eine Komponente ändert eine unkontrollierte Eingabe des zu steuernden Texttyps. Eingangselemente sollten nicht von unkontrolliert zu kontrolliert (oder umgekehrt) wechseln. Entscheiden Sie sich für die Lebensdauer der Komponente zwischen der Verwendung eines gesteuerten oder unkontrollierten Eingabeelements.

Lösung: Überprüfen Sie, ob der Wert nicht undefiniert ist

Reagieren Sie / Formik / Bootstrap / TypeScript

Beispiel:

{ values?.purchaseObligation.remainingYear ?
  <Input
   tag={Field}
   name="purchaseObligation.remainingYear"
   type="text"
   component="input"
  /> : null
}
user3706761
quelle