Memperbarui sebuah objek dengan setState dalam Bereaksi

Itu adalah mungkin untuk memperbarui objek's properties dengan setState?

Sesuatu seperti:

this.state = {
   jasper: { name: 'jasper', age: 28 },
}

Saya telah mencoba:

this.setState({jasper.name: 'someOtherName'});

dan ini:

this.setState({jasper: {name: 'someothername'}})

Hasil pertama dalam kesalahan sintaks dan kedua hanya tidak apa-apa. Ada ide?

Mengomentari pertanyaan (1)
Larutan

Ada beberapa cara untuk melakukan hal ini, karena negara update operasi asinkron, jadi untuk memperbarui keadaan objek, kita perlu menggunakan fungsi updater dengan setState.

1 - Sederhana satu:

Pertama membuat copy dari jasper kemudian melakukan perubahan dalam:

this.setState(prevState => {
  let jasper = Object.assign({}, prevState.jasper);  // creating copy of state variable jasper
  jasper.name = 'someothername';                     // update the name property, assign a new value                 
  return { jasper };                                 // return new object jasper object
})

Alih-alih menggunakan Objek.menetapkan kita bisa juga menulis seperti ini:

let jasper = { ...prevState.jasper };

2 - Menggunakan [menyebar operator]3:

this.setState(prevState => ({
    jasper: {                   // object that we want to update
        ...prevState.jasper,    // keep all other key-value pairs
        name: 'something'       // update the value of specific key
    }
}))

Catatan: Objek.menetapkan dan Menyebar Operator hanya menciptakan dangkal salin, jadi jika anda memiliki didefinisikan nested object atau array dari objek, anda membutuhkan pendekatan yang berbeda.


Memperbarui bersarang keadaan objek:

Asumsikan anda memiliki negara didefinisikan sebagai:

this.state = {
  food: {
    sandwich: {
      capsicum: true,
      crackers: true,
      mayonnaise: true
    },
    pizza: {
      jalapeno: true,
      extraCheese: false
    }
  }
}

Untuk update extraCheese pizza objek:

this.setState(prevState => ({
  food: {
    ...prevState.food,           // copy all other key-value pairs of food object
    pizza: {                     // specific object of food object
      ...prevState.food.pizza,   // copy all pizza key-value pairs
      extraCheese: true          // update value of specific key
    }
  }
}))

Memperbarui array dari objek:

Mari kita asumsikan anda memiliki sebuah aplikasi todo, dan anda mengelola data-data di formulir ini:

this.state = {
  todoItems: [
    {
      name: 'Learn React Basics',
      status: 'pending'
    }, {
      name: 'Check Codebase',
      status: 'pending'
    }
  ]
}

Untuk update status setiap todo objek, menjalankan sebuah peta pada array dan memeriksa beberapa nilai yang unik dari setiap objek, dalam kasus kondisi=true, kembali objek baru dengan diperbarui nilai, yang lain objek yang sama.

let key = 2;
this.setState(prevState => ({

  todoItems: prevState.todoItems.map(
    el => el.key === key? { ...el, status: 'done' }: el
  )

}))

Saran: Jika obyek doesn't memiliki nilai yang unik, maka digunakan indeks array.

Komentar (11)

Ini adalah cara tercepat dan paling dapat dibaca dengan cara:

this.setState({...this.state.jasper, name: 'someothername'});

Bahkan jika ini.negara.jasper sudah berisi nama tamu, nama baru nama: 'someothername' dengan yang akan digunakan.

Komentar (1)

Gunakan menyebar operator dan beberapa ES6 di sini

this.setState({
    jasper: {
          ...this.state.jasper,
          name: 'something'
    }
})
Komentar (1)

Saya menggunakan solusi ini.

Jika anda memiliki bersarang negara seperti ini: ini.negara = { formInputs:{ friendName:{ nilai:'', isValid:false, errorMsg:'' }, friendEmail:{ nilai:'', isValid:false, errorMsg:'' } } } anda dapat mendeklarasikan handleChange fungsi yang salin status dan kembali memberikan itu dengan mengubah nilai-nilai

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let statusCopy = Object.assign({}, this.state);
    statusCopy.formInputs[inputName].value = inputValue;

    this.setState(statusCopy);
  }

di sini html dengan acara pendengar. Pastikan untuk menggunakan nama yang sama digunakan dalam keadaan objek (dalam hal ini 'friendName')

<input type="text" onChange={this.handleChange} " name="friendName" />
Komentar (0)

mencoba ini,itu harus bekerja dengan baik

this.setState(Object.assign(this.state.jasper,{name:'someOtherName'}));
Komentar (1)

Kasus pertama adalah memang sebuah kesalahan sintaks.

Karena saya dapat't melihat sisa komponen,'s sulit untuk melihat mengapa anda're bersarang benda-benda dalam negara anda di sini. It's bukan ide yang baik untuk sarang objek dalam komponen negara. Mencoba menetapkan keadaan awal menjadi:

this.state = {
  name: 'jasper',
  age: 28
}

Dengan cara itu, jika anda ingin update nama, anda hanya dapat menghubungi:

this.setState({
  name: 'Sean'
});

Itu akan mencapai apa yang anda're bertujuan untuk?

Untuk yang lebih besar, lebih kompleks data toko, saya akan menggunakan sesuatu seperti Redux. Tapi yang's jauh lebih maju.

Aturan umum dengan komponen negara adalah untuk menggunakannya hanya untuk mengelola UI keadaan komponen (misalnya aktif, timer, dll.)

Memeriksa referensi ini:

Komentar (2)

Pilihan lain: menentukan variabel dari Jasper objek dan kemudian hanya memanggil variabel.

Menyebar operator: ES6

this.state = {  jasper: { name: 'jasper', age: 28 } } 

let foo = "something that needs to be saved into state" 

this.setState(prevState => ({
    jasper: {
        ...jasper.entity,
        foo
    }
})
Komentar (1)

Saya tahu ada banyak jawaban di sini, tapi saya'm terkejut tidak satupun dari mereka membuat salinan objek baru di luar setState, dan kemudian hanya setState({newObject}). Bersih, ringkas dan dapat diandalkan. Jadi dalam hal ini:

const jasper = { ...this.state.jasper, name: 'someothername' }
this.setState(prevState => ({ jasper }))

Atau untuk properti dinamis (sangat berguna untuk bentuk-bentuk)

const jasper = { ...ini.negara.jasper, [VarRepresentingPropertyName]: 'nilai baru' } ini.setState(prevState => ({ jasper }))

Komentar (0)

Anda dapat mencoba dengan ini:

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.name = 'someOtherName';
   return {jasper: prevState}
})

atau untuk properti lainnya:

this.setState(prevState => {
   prevState = JSON.parse(JSON.stringify(this.state.jasper));
   prevState.age = 'someOtherAge';
   return {jasper: prevState}
})

Atau anda dapat menggunakan handleChage fungsi:

handleChage(event) {
   const {name, value} = event.target;
    this.setState(prevState => {
       prevState = JSON.parse(JSON.stringify(this.state.jasper));
       prevState[name] = value;
       return {jasper: prevState}
    })
}

dan kode HTML:

<input 
   type={"text"} 
   name={"name"} 
   value={this.state.jasper.name} 
   onChange={this.handleChange}
/>
<br/>
<input 
   type={"text"} 
   name={"age"} 
   value={this.state.jasper.age} 
   onChange={this.handleChange}
/>
Komentar (1)

Anda dapat mencoba dengan ini: (Catatan: nama masukan tag === bidang objek) `` <input name="myField" type="text" nilai={ini.negara.myObject.myField} onChange={ini.handleChangeInpForm}>

< input>

handleChangeInpForm = (e) => { mari newObject = ini.negara.myObject; newObject[e.target.name] = e.target.nilai; ini.setState({ myObject: newObject }) } ``

Komentar (1)

Sederhana dan cara dinamis.

Ini akan melakukan pekerjaan, tetapi anda perlu untuk mengatur semua id ke orang tua sehingga orang tua akan mengarah ke nama objek, menjadi id = "jasper" dan nama-nama elemen input = properti di dalam objek jasper.

handleChangeObj = ({target: { id , name , value}}) => this.setState({ [id]: { ...this.state[id] , [name]: value } });
Komentar (0)

Tanpa menggunakan Async dan Menanti Menggunakan ini...

funCall(){    
     this.setState({...this.state.jasper, name: 'someothername'});
}

Jika anda menggunakan dengan Async Dan Menanti menggunakan ini...

async funCall(){
      await this.setState({...this.state.jasper, name: 'someothername'});
}
Komentar (0)

Juga, berikut Alberto Piras solusi, jika anda don't ingin menyalin semua "negara" obyek:

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let jasperCopy = Object.assign({}, this.state.jasper);
    jasperCopy[inputName].name = inputValue;

    this.setState({jasper: jasperCopy});
  }
Komentar (0)

ini adalah solusi lain menggunakan immer immutabe utilitas, sangat cocok untuk sangat bersarang benda dengan mudah, dan anda tidak harus peduli tentang mutasi

this.setState(
    produce(draft => {
       draft.jasper.name = 'someothername
    })
)
Komentar (0)