Komponen mengubah input teks tipe yang tidak terkontrol menjadi kesalahan terkontrol di ReactJS

331

Peringatan: Komponen mengubah input teks tipe yang tidak terkontrol untuk dikontrol. Elemen input tidak boleh beralih dari tidak terkontrol ke terkontrol (atau sebaliknya). Putuskan antara menggunakan elemen input yang dikontrol atau tidak dikontrol selama masa pakai komponen. *

Berikut ini adalah kode saya:

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
sumber
2
apa nilai awal fieldsdalam keadaan?
Mayank Shukla
2
constructor (props) {super (props); this.state = {bidang: {}, kesalahan: {}} this.onSubmit = this.onSubmit.bind (this); }
Riya Kapuria
2
Kemungkinan duplikat Bereaksi - mengubah input yang tidak terkontrol
Michael Freidgeim

Jawaban:

651

Alasannya adalah, dalam status yang Anda tentukan:

this.state = { fields: {} }

bidang sebagai objek kosong, jadi selama rendering pertama this.state.fields.nameakan undefined, dan bidang input akan mendapatkan nilainya sebagai:

value={undefined}

Karena itu, bidang input akan menjadi tidak terkontrol.

Setelah Anda memasukkan nilai apa pun dalam input, fieldsstatus diubah menjadi:

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

Dan pada saat itu bidang input akan dikonversi menjadi komponen yang dikendalikan; itu sebabnya Anda mendapatkan kesalahan:

Komponen mengubah input teks tipe yang tidak terkontrol untuk dikontrol.

Solusi yang memungkinkan:

1- Tetapkan status fieldsdalam sebagai:

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

2- Atau mendefinisikan properti nilai dengan menggunakan evaluasi hubung singkat seperti ini:

value={this.state.fields.name || ''}   // (undefined || '') = ''
Mayank Shukla
sumber
5
adakah alasan yang tidak terdefinisi "tidak terkendali" sementara yang terakhir "dikontrol" - apa artinya ini?
Prashanth Subramanian
2
karena ''merupakan nilai string yang valid. jadi ketika Anda mengubah ''ke 'xyz', tipe input tidak berubah berarti dikontrol menjadi terkontrol. Tapi dalam kasus undefineduntuk xyzjenis akan berubah dari tidak terkendali ke dikendalikan.
Mayank Shukla
1
Terima kasih, ini berhasil untuk saya:value={this.state.fields.name || ''}
Bob
1
Saya tidak tahu bahwa begitu nilai menjadi tidak terdefinisi, input menjadi otomatis tidak terkontrol, Hebat. Sudah memperbaiki masalah saya
Adrian Serna
1
luar biasa! karena saya tidak melihat ini disebutkan dalam dokumen resmi, atau apakah saya buta? tolong tautkan ke sumber :)
Dheeraj
34

Mengubah valueke defaultValueakan menyelesaikannya.

Catatan :

defaultValuehanya untuk beban awal. Jika Anda ingin menginisialisasi inputmaka Anda harus menggunakan defaultValue, tetapi jika Anda ingin menggunakan stateuntuk mengubah nilai maka Anda perlu menggunakan value. Baca ini untuk lebih lanjut.

Aku digunakan value={this.state.input ||""}dalam inputuntuk menyingkirkan peringatan itu.

MoFoLuWaSo
sumber
2
Terima kasih! Saya menemukan masalah ini dan solusi lain tidak berlaku untuk saya, tetapi solusi ini membantu.
PepperAddict
14

Di dalam komponen, masukkan kotak input dengan cara berikut.

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

SIMPLY, Anda harus mengatur keadaan awal terlebih dahulu

Jika Anda tidak menyetel keadaan awal, reaksi akan menganggapnya sebagai komponen yang tidak terkontrol

Vaibhav Bacchav
sumber
10

Selain jawaban yang diterima, jika Anda menggunakan inputtipe checkboxatau radio, saya menemukan saya perlu null / undefined memeriksa checkedatribut juga.

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

Dan jika Anda menggunakan TS (atau Babel), Anda bisa menggunakan nullish coalescing alih-alih operator logika ATAU:

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

Tetapkan Status Saat Ini terlebih dahulu ...this.state

Itu karena ketika Anda akan menetapkan negara baru itu mungkin tidak terdefinisi. jadi itu akan diperbaiki dengan mengatur status mengekstraksi kondisi saat ini juga

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

Jika ada objek di negara Anda, Anda harus menetapkan negara sebagai berikut, misalkan Anda harus mengatur nama pengguna di dalam objek pengguna.

this.setState({user:{...this.state.user, ['username']: username}})
NuOne
sumber
1
Sejauh yang saya mengerti, setState sudah hanya menimpa bidang, jadi dalam kasus pertama seharusnya tidak perlu merusak penugasan. Dalam keadaan kedua itu mungkin diperlukan karena setState akan menggantikan grosir sub-objek.
Kzqai
6
const [name, setName] = useState()

menghasilkan kesalahan segera setelah Anda mengetik di bidang teks

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

akan memperbaiki masalah pada contoh string ini.

Nelles
sumber
2

Jika Anda menggunakan beberapa input pada bidang, ikuti: Misalnya:

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

Cari masalah Anda di:

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
sumber
1

Menggunakan React Hooks juga jangan lupa untuk menetapkan nilai awal.
Saya menggunakan <input type='datetime-local' value={eventStart} />dan inisial eventStartseperti

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

String kosong dalam tanda kurung adalah perbedaan.
Juga, jika Anda mengatur ulang formulir setelah mengirim seperti saya lakukan, sekali lagi Anda perlu mengaturnya ke string kosong, bukan hanya untuk mengurung tanda kurung.

Ini hanyalah kontribusi kecil saya untuk topik ini, mungkin itu akan membantu seseorang.

Zrna
sumber
0

Dalam kasus saya, itu adalah apa yang dikatakan oleh jawaban teratas Mayank Shukla. Satu-satunya detail adalah keadaan saya kurang sepenuhnya properti yang saya mendefinisikan.

Misalnya, jika Anda memiliki status ini:

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

Jika Anda memperluas kode Anda, Anda mungkin ingin menambahkan properti baru jadi, di tempat lain dalam kode Anda, Anda dapat membuat properti baru cyang nilainya tidak hanya tidak ditentukan pada keadaan komponen tetapi properti itu sendiri tidak terdefinisi.

Untuk mengatasi ini, pastikan untuk menambahkan cke negara Anda dan berikan nilai awal yang tepat.

misalnya,

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

Semoga saya bisa menjelaskan kasus tepi saya.

Daniel Segura
sumber
0

Saya mendapatkan peringatan yang sama: Komponen mengubah input tipe yang tidak terkontrol yang disembunyikan untuk dikendalikan. Saya tidak dapat memperbaiki masalah saya. Ada ide kenapa?

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>

saya mencoba ({ valueName, valueName: {geschlecht=""}, onChangeAllg,})danvalue={valueName.geschlecht || ""}

Malte Westerloh
sumber
aku menemukannya. Bagian defaultValue={""}dalam TextField hilang
Dr. Malte Westerloh
0

Peringatan: Komponen mengubah input teks tipe yang tidak terkontrol untuk dikontrol. Elemen input tidak boleh beralih dari tidak terkontrol ke terkontrol (atau sebaliknya). Putuskan antara menggunakan elemen input yang dikontrol atau tidak dikontrol selama masa pakai komponen.

Solusi: Periksa apakah nilainya tidak ditentukan

Bereaksi / Formik / Bootstrap / TypeScript

contoh:

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