cara apa yang lebih disukai untuk mengubah status React?

97

Katakanlah saya memiliki daftar objek polos this.state.listyang kemudian dapat saya gunakan untuk membuat daftar anak-anak. Lalu bagaimana cara yang benar untuk memasukkan objek this.state.list?

Di bawah ini adalah satu-satunya cara yang menurut saya akan berhasil karena Anda tidak dapat memutasi this.statesecara langsung seperti yang disebutkan dalam dokumen.

this._list.push(newObject):
this.setState({list: this._list});

Ini tampak jelek bagi saya. Apakah ada cara yang lebih baik?

Khoi
sumber
kemungkinan duplikat modifikasi yang benar dari susunan negara di ReactJS , meminta penggabungan
Brigand
Semua jawaban itu tentang menambahkan elemen ke array. Tapi bagaimana dengan menghilangkan elemen darinya? Atau hanya untuk mereset array sepenuhnya ke yang baru?
Augustin Riedinger

Jawaban:

165

concat mengembalikan array baru, jadi Anda bisa melakukannya

this.setState({list: this.state.list.concat([newObject])});

alternatif lain adalah pembantu keabadian React

  var newState = React.addons.update(this.state, {
      list : {
        $push : [newObject]
      }
  });

  this.setState(newState);
Tumpukan
sumber
6
concatmengambil sebuah array, jadi Anda akan menginginkannya this.state.list.concat([newObject]).
Sophie Alpert
@BenAlpert berfungsi untuk saya di Chrome, apakah Anda mengatakan ini adalah perilaku non-standar?
Heap
6
@Heap Nah, jika Anda meneruskan non-array ke concatdalamnya akan membungkusnya dalam array, tetapi lebih baik menambahkan array sendiri agar eksplisit: jika Anda memiliki [[1,2], [3,4]]dan ingin menambahkan [5,6]sebagai elemen berikutnya, Anda perlu melakukan yang .concat([[5,6]])lain Anda akan berakhir dengan [[1,2], [3,4], 5, 6].
Sophie Alpert
2
Sebanyak saya menghargai ide di balik immutability helper (dan saya mungkin akan tetap menggunakannya), Array.concatpasti lebih baik menambahkan perpustakaan lain.
Shawn Erquhart
1
Memanggil this.setState dengan nilai yang diturunkan dari this.state akan membuat Anda terkena masalah pengelompokan pembaruan. Lihat stackoverflow.com/a/41445812/1998186 yang menautkan ke jsfiddle yang menunjukkan masalah yang akan Anda dapatkan.
NealeU
40

setState () bisa dipanggil dengan fungsi sebagai parameter:

this.setState((state) => ({ list: state.list.concat(newObj) }))

atau di ES5:

this.setState(function(state) {
  return {
   list: state.list.concat(newObj)
  }
})
Nyalab
sumber
2
@Arian: React akan mengeksekusi instruksi mutasi DOM yang diperlukan untuk merender hanya elemen yang baru ditambahkan. Mengingat tentu saja Anda menambahkan elemen yang baru tidak mengubah bagaimana elemen sebelumnya dirender.
Jose Browne
1
Ini adalah jawaban yang fantastis dan terasa jauh lebih bersih daripada merangkai array hanya untuk melakukan push, meskipun itu pendapat saya.
Matt Styles
2
@ Nyalab bukankah seharusnya Anda membungkus badan fungsi dalam tanda kurung? Seperti saat ini dalam contoh Anda, kawat gigi setelah panah tebal akan memulai blok, bukan objek. Sesuatu seperti ini:this.setState((state) => ({ list: state.list.push(newObj) }))
kumarharsh
3
Bagaimana kode ini bekerja? metode push akan mengembalikan a NUMBER, yang akan disetel pada listvariabel
kumarharsh
1
Anda juga bisa menggunakan gambar percikan:this.setState((state) => ({ list: [...state.list, newObj] }))
amoebe
19

Perbarui 2016

Dengan ES6 Anda dapat menggunakan:

this.setState({ list: [...this.state.list, ...newObject] });
Ashish Chaudhary
sumber
5
...[newObject]sama dengan adil newObject.
amoebe
2
Ini tidak akan berfungsi untuk pembaruan berkelompok. Lihat contoh saya di stackoverflow.com/a/41445812/1998186 .
NealeU