Saya memiliki status berikut:
this.setState({ selected: { id: 1, name: 'Foobar' } });
Lalu saya memperbarui status:
this.setState({ selected: { name: 'Barfoo' }});
Karena setState
seharusnya bergabung saya harapkan itu menjadi:
{ selected: { id: 1, name: 'Barfoo' } };
Tetapi sebaliknya ia memakan id dan negara bagian adalah:
{ selected: { name: 'Barfoo' } };
Apakah perilaku yang diharapkan ini dan apa solusinya untuk memperbarui hanya satu properti dari objek keadaan bersarang?
sumber
this.setState({ selected: { ...this.state.selected, name: 'barfoo' } })
yang diterjemahkan kethis.setState({ selected: _extends({}, this.state.selected, { name: 'barfoo' }) });
underscore
/lodash
. Tolong, ubah menjadi jawaban sendiri.this.state
belum tentu terkini . Anda bisa mendapatkan hasil yang tidak terduga menggunakan metode perluasan. Melewati fungsi pembaruansetState
adalah solusi yang benar.Pembantu ketidaksuburan baru-baru ini ditambahkan ke React.addons, jadi dengan itu, Anda sekarang dapat melakukan sesuatu seperti:
Dokumentasi pembantu ketidakmampuan .
sumber
React.addons.update()
metode ini sudah usang, tetapi pustaka pengganti github.com/kolodny/immutability-helper berisiupdate()
fungsi yang setara .Karena banyak jawaban menggunakan kondisi saat ini sebagai dasar untuk menggabungkan data baru, saya ingin menunjukkan bahwa ini bisa pecah. Status perubahan di-antri, dan jangan langsung mengubah objek status komponen. Karenanya merujuk data keadaan sebelum antrian diproses akan memberi Anda data basi yang tidak mencerminkan perubahan yang tertunda yang Anda buat di setState. Dari dokumen:
Ini berarti menggunakan status "saat ini" sebagai referensi dalam panggilan berikutnya ke setState tidak dapat diandalkan. Sebagai contoh:
Jika Anda perlu menggunakan status saat ini (misalnya untuk menggabungkan data menjadi objek bersarang), setState menerima fungsi sebagai argumen alih-alih objek; fungsi dipanggil setelah setiap pembaruan sebelumnya ke negara, dan melewati negara sebagai argumen - jadi ini dapat digunakan untuk membuat perubahan atom dijamin untuk menghormati perubahan sebelumnya.
sumber
this.state
, yang mungkin basi (atau lebih tepatnya, pembaruan antrian menunggu) ketika Anda mengaksesnya.Saya tidak ingin menginstal perpustakaan lain jadi inilah solusi lain.
Dari pada:
Lakukan ini sebagai gantinya:
Atau, terima kasih kepada @ icc97 dalam komentarnya, bahkan lebih singkat tetapi tidak terlalu mudah dibaca:
Juga, untuk menjadi jelas, jawaban ini tidak melanggar kekhawatiran apa pun yang @bgannonpl sebutkan di atas.
sumber
this.setState({ selected: Object.assign(this.state.selected, { name: "Barfoo" }));
Object.assign(a, b)
mengambil atribut darib
, masukkan / timpa merekaa
dan kemudian kembalia
. Bereaksi orang menjadi bersemangat jika Anda mengubah keadaan secara langsung.{}
sebagai argumen pertama:this.setState({ selected: Object.assign({}, this.state.selected, { name: "Barfoo" }) });
. Ini tidak mengubah status awal.Mempertahankan status sebelumnya berdasarkan jawaban @bgannonpl:
Contoh Lodash :
Untuk memeriksa apakah itu berfungsi dengan baik, Anda dapat menggunakan panggilan fungsi parameter kedua:
Saya menggunakan
merge
karenaextend
membuang properti lain jika tidak.Contoh Kekebalan Bereaksi :
sumber
Solusi saya untuk situasi seperti ini adalah menggunakan, seperti jawaban lain yang ditunjukkan, para Pembantu Ketidakmampuan .
Karena mengatur keadaan secara mendalam adalah situasi yang umum, saya telah membuat mixin berikut:
Mixin ini termasuk dalam sebagian besar komponen saya dan saya biasanya tidak menggunakan
setState
langsung lagi.Dengan mixin ini, yang perlu Anda lakukan untuk mencapai efek yang diinginkan adalah memanggil fungsi
setStateinDepth
dengan cara berikut:Untuk informasi lebih lanjut:
setStateinDepth
melihat dokumentasi Immutability Helpers .sumber
this.state.test.two
akan tetap ada di sana setelah Anda memperbaruithis.state.test.one
menggunakansetStateInDepth({test: {one: {$set: 'new-value'}}})
. Saya menggunakan kode ini di semua komponen saya untuk menyiasatisetState
fungsi terbatas React .this.state.test
sebagai Array. Mengubah ke Objek, menyelesaikannya.Saya menggunakan kelas es6, dan saya berakhir dengan beberapa objek kompleks pada kondisi teratas saya dan berusaha membuat komponen utama saya lebih modular, jadi saya membuat pembungkus kelas sederhana untuk menjaga status pada komponen atas tetapi memungkinkan lebih banyak logika lokal .
Kelas wrapper mengambil fungsi sebagai konstruktornya yang menetapkan properti pada status komponen utama.
Kemudian untuk setiap properti kompleks di negara bagian atas, saya membuat satu kelas StateWrapped. Anda dapat mengatur alat peraga default di konstruktor di sini dan mereka akan ditetapkan ketika kelas diinisialisasi, Anda dapat merujuk ke negara lokal untuk nilai dan mengatur negara setempat, merujuk ke fungsi lokal, dan telah melewati rantai:
Jadi komponen tingkat atas saya hanya perlu konstruktor untuk mengatur setiap kelas ke properti negara tingkat atas itu, render sederhana, dan fungsi apa pun yang berkomunikasi lintas-komponen.
Tampaknya berfungsi cukup baik untuk keperluan saya, ingatlah meskipun Anda tidak dapat mengubah keadaan properti yang Anda tetapkan untuk komponen terbungkus pada komponen tingkat atas karena setiap komponen terbungkus melacak keadaannya sendiri tetapi memperbarui keadaan pada komponen atas setiap kali itu berubah.
sumber
Sampai sekarang,
menurut dokumentasi https://reactjs.org/docs/react-component.html#setstate , menggunakan:
sumber
Larutan
Sunting: Solusi ini digunakan untuk menggunakan sintaks spread . Tujuannya adalah membuat objek tanpa referensi
prevState
, sehinggaprevState
tidak akan dimodifikasi. Tetapi dalam penggunaan saya,prevState
kadang-kadang tampaknya dimodifikasi. Jadi, untuk kloning sempurna tanpa efek samping, kami sekarang mengonversiprevState
ke JSON, dan kemudian kembali lagi. (Inspirasi untuk menggunakan JSON berasal dari MDN .)Ingat:
setState(prevState => stateChange)
Langkah
state
yang Anda ingin perubahanLangkah 3 dan 4 dapat digabungkan dalam satu baris.
Contoh
Contoh sederhana:
Ini mengikuti pedoman Bereaksi dengan baik. Berdasarkan jawaban eicksl untuk pertanyaan serupa.
sumber
Solusi ES6
Kami mengatur negara awalnya
Kami mengubah properti pada beberapa tingkat objek negara:
sumber
React state tidak melakukan penggabungan rekursif
setState
sementara berharap tidak akan ada pembaruan anggota negara di tempat pada saat yang sama. Anda juga harus menyalin sendiri objek / array yang terlampir (dengan array.slice atau Object.assign) atau menggunakan perpustakaan khusus.Seperti yang ini. NestedLink secara langsung mendukung penanganan senyawa React state.
Juga, tautan ke
selected
atauselected.name
dapat diteruskan ke mana saja sebagai penyangga tunggal dan dimodifikasi di sana bersamaset
.sumber
Sudahkah Anda mengatur kondisi awal?
Saya akan menggunakan beberapa kode saya sendiri misalnya:
Dalam aplikasi yang sedang saya kerjakan, ini adalah cara saya mengatur dan menggunakan status. Saya yakin
setState
Anda dapat mengedit saja status apa pun yang Anda inginkan secara individual. Saya menyebutnya seperti ini:Ingatlah bahwa Anda harus mengatur status di dalam
React.createClass
fungsi yang Anda panggilgetInitialState
sumber
Saya menggunakan tmp var untuk berubah.
sumber
let original = {a:1}; let tmp = original; tmp.a = 5; // original is now === Object {a: 5}
Jangan lakukan ini, bahkan jika itu belum memberi Anda masalah.