Komponent zmienia niekontrolowane wprowadzanie tekstu tekstowego w celu kontrolowania błędu w ReactJS


331

Ostrzeżenie: składnik zmienia niekontrolowane wprowadzanie tekstu tekstowego, który ma być kontrolowany. Elementy wejściowe nie powinny przełączać się z niekontrolowanego na kontrolowane (lub odwrotnie). Wybierz między użyciem kontrolowanego lub niekontrolowanego elementu wejściowego przez cały okres użytkowania komponentu. *

Oto mój kod:

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
Jaka jest początkowa wartość fieldsw stanie?
Mayank Shukla

2
konstruktor (rekwizyty) {super (rekwizyty); this.state = {pola: {}, błędy: {}} this.onSubmit = this.onSubmit.bind (this); }
Riya Kapuria

Odpowiedzi:


650

Powodem jest, w stanie, który zdefiniowałeś:

this.state = { fields: {} }

pola jako pusty obiekt, więc podczas pierwszego renderowania this.state.fields.namebędzie undefined, a pole wejściowe otrzyma swoją wartość jako:

value={undefined}

Z tego powodu pole wejściowe stanie się niekontrolowane.

Po wprowadzeniu dowolnej wartości na wejściu fieldsstan zmienia się na:

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

W tym czasie pole wejściowe zostaje przekształcone w kontrolowany komponent; dlatego pojawia się błąd:

Komponent zmienia niekontrolowane wprowadzanie tekstu tekstowego, który ma być kontrolowany.

Możliwe rozwiązania:

1- Zdefiniuj fieldsstan w:

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

2- Lub zdefiniuj właściwość wartości za pomocą oceny zwarcia w następujący sposób:

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

5
czy istnieje nieokreślony powód, który jest „niekontrolowany”, podczas gdy ten drugi jest „kontrolowany” - co one oznaczają?
Prashanth Subramanian

2
ponieważ ''jest poprawną wartością ciągu. więc kiedy zmienisz ''na „xyz”, typ danych wejściowych nie zmienia środków kontrolowanych na kontrolowane. Jednak w przypadku undefineddo xyzrodzaju zmieni się z niekontrolowanym do kontrolowany.
Mayank Shukla

1
Dziękuję, że to zadziałało dla mnie:value={this.state.fields.name || ''}
Bob

1
Nie wiedziałem, że gdy wartość stanie się niezdefiniowana, dane wejściowe zostaną automatycznie niekontrolowane, Świetnie. Naprawiłem już mój problem
Adrian Serna

1
niesamowity! ponieważ nie widziałem tego w oficjalnych dokumentach, czy jestem ślepy? link do źródła proszę :)
Dheeraj

34

Zmiana valuena defaultValueto rozwiąże.

Uwaga :

defaultValuejest tylko dla początkowego obciążenia. Jeśli chcesz zainicjować input, powinieneś użyć defaultValue, ale jeśli chcesz użyć statedo zmiany wartości, musisz użyć value. Przeczytaj to, aby uzyskać więcej.

Kiedyś value={this.state.input ||""}w inputpozbyć się tego ostrzeżenia.


2
Dziękuję Ci! Natknąłem się na ten problem i inne rozwiązania mnie nie dotyczyły, ale to rozwiązanie pomogło.
PepperAddict

14

Wewnątrz komponentu umieść pole wprowadzania w następujący sposób.

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

13

PO PROSTU, najpierw musisz ustawić stan początkowy

Jeśli nie ustawisz stanu początkowego, zareaguj potraktuje to jako niekontrolowany komponent


10

Oprócz zaakceptowanej odpowiedzi, jeśli używasz inputtypu checkboxlub radio, stwierdziłem, że muszę również zerować / niezdefiniować sprawdzenie checkedatrybutu.

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

A jeśli używasz TS (lub Babel), możesz użyć zerowego koalescencji zamiast logicznego operatora OR:

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

8

Najpierw ustaw bieżący stan ...this.state

Dzieje się tak, ponieważ gdy zamierzasz przypisać nowy stan, może on być niezdefiniowany. więc zostanie to naprawione poprzez ustawienie stanu wyodrębniania bieżącego stanu również

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

Jeśli w twoim stanie jest obiekt, powinieneś ustawić go w następujący sposób, załóżmy, że musisz ustawić nazwę użytkownika wewnątrz obiektu użytkownika.

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

1
O ile rozumiem, setState już tylko zastępuje pola, więc w pierwszym przypadku przypisanie destrukcji nie powinno być konieczne. W drugim stanie może być konieczne, ponieważ setState zastąpi hurtownie podobiekt.
Kzqai

6
const [name, setName] = useState()

generuje błąd, gdy tylko wpiszesz w polu tekstowym

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

naprawi problem na tym przykładzie ciągu.


2

Jeśli używasz wielu danych wejściowych w polu, wykonaj następujące czynności: Na przykład:

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

Wyszukaj swój problem na:

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

1

Używając React Hook również nie zapomnij ustawić wartości początkowej.
Używałem <input type='datetime-local' value={eventStart} />i początkowy eventStartbył jak

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

Pusty ciąg w nawiasach to różnica.
Ponadto, jeśli zresetujesz formularz po przesłaniu, tak jak ja, ponownie musisz ustawić go jako pusty ciąg, a nie tylko puste nawiasy.

To tylko mój mały wkład w ten temat, może komuś pomoże.


0

W moim przypadku było tak, jak mówi najlepsza odpowiedź Mayanka Shukli. Jedynym szczegółem było to, że w moim stanie brakowało całkowicie właściwości, którą definiowałem.

Na przykład, jeśli masz ten stan:

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

Jeśli rozwijasz swój kod, możesz dodać nowy rekwizyt, więc w innym miejscu w kodzie możesz utworzyć nową właściwość, cktórej wartość jest nie tylko niezdefiniowana w stanie składnika, ale sama właściwość jest niezdefiniowana.

Aby rozwiązać ten problem, po prostu dodaj cdo swojego stanu i nadaj mu odpowiednią wartość początkową.

na przykład,

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

Mam nadzieję, że udało mi się wyjaśnić mój przypadek.


0

Otrzymuję to samo ostrzeżenie: komponent zmienia niekontrolowane dane wejściowe typu ukryte, aby je kontrolować. Nie mogę naprawić mojego problemu. Jakieś pomysły, dlaczego?

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>

próbowałem ({ valueName, valueName: {geschlecht=""}, onChangeAllg,})ivalue={valueName.geschlecht || ""}


znalazłem to. defaultValue={""}Wewnątrz TextField brakowało
dr Malte Westerloh

0

Ostrzeżenie: składnik zmienia niekontrolowane wprowadzanie tekstu tekstowego, który ma być kontrolowany. Elementy wejściowe nie powinny przełączać się z niekontrolowanego na kontrolowane (lub odwrotnie). Wybierz pomiędzy użyciem kontrolowanego lub niekontrolowanego elementu wejściowego przez cały okres użytkowania komponentu.

Rozwiązanie: Sprawdź, czy wartość nie jest niezdefiniowana

React / Formik / Bootstrap / TypeScript

przykład:

{ values?.purchaseObligation.remainingYear ?
  <Input
   tag={Field}
   name="purchaseObligation.remainingYear"
   type="text"
   component="input"
  /> : null
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.