Saya mencoba mengatur negara saya dengan menggunakan properti bersarang seperti ini:
this.state = {
someProperty: {
flag:true
}
}
Tapi memperbarui keadaan seperti ini,
this.setState({ someProperty.flag: false });
tidak bekerja Bagaimana ini bisa dilakukan dengan benar?
javascript
reactjs
ecmascript-6
setstate
Alex Yong
sumber
sumber
Jawaban:
Untuk
setState
objek bersarang Anda dapat mengikuti pendekatan di bawah ini karena saya pikir setState tidak menangani pembaruan bersarang.Idenya adalah untuk membuat objek dummy melakukan operasi di atasnya dan kemudian mengganti status komponen dengan objek yang diperbarui
Sekarang, operator spread hanya membuat salinan level objek bersarang satu tingkat. Jika keadaan Anda sangat bersarang seperti:
Anda bisa mengaturState menggunakan operator spread di setiap level seperti
Namun sintaks di atas mendapatkan setiap jelek karena negara menjadi lebih dan lebih bersarang dan karenanya saya sarankan Anda untuk menggunakannya
immutability-helper
paket untuk memperbarui keadaan.Lihat jawaban ini tentang cara memperbarui status dengan
immutability helper
.sumber
someProperty
dan kami memodifikasi ituthis.setState((prevState) => ({nested: {...prevState.nested, propertyToSet: newValue}})
Agak membosankan ......prevState,
dalam contoh terakhir, Anda hanyasomeProperty
dan anak-anaknyaUntuk menulisnya dalam satu baris
sumber
this.state
segera setelah itusetState
dan berharap itu memiliki nilai baru. Versus menelepon dithis.state
dalamsetState
. Atau ada juga masalah dengan yang terakhir yang tidak jelas bagi saya?this.state
setelahsetState
. Selain itu, kita tidak lulusthis.state
untuksetState
. The…
Operator spread properti. Itu sama dengan Object.assign (). github.com/tc39/proposal-object-rest-spreadthis.setState(currentState => { someProperty: { ...currentState.someProperty, flag: false} });
memungkinkan untuk menghindari masalah ini?Terkadang jawaban langsung bukan yang terbaik :)
Versi pendek:
kode ini
harus disederhanakan sebagai sesuatu seperti
Versi panjang:
Saat ini Anda seharusnya tidak ingin bekerja dengan status bersarang di Bereaksi . Karena Bereaksi tidak berorientasi untuk bekerja dengan negara-negara bersarang dan semua solusi yang diusulkan di sini terlihat sebagai peretasan. Mereka tidak menggunakan kerangka kerja tetapi bertarung dengannya. Mereka menyarankan untuk menulis kode yang tidak begitu jelas untuk tujuan pengelompokan beberapa properti. Jadi mereka sangat menarik sebagai jawaban untuk tantangan tetapi praktis tidak berguna.
Mari kita bayangkan keadaan berikut:
Apa yang akan terjadi jika Anda mengubah hanya nilai
child1
? Bereaksi tidak akan merender ulang tampilan karena menggunakan perbandingan yang dangkal dan akan menemukan ituparent
properti tidak berubah. BTW bermutasi objek negara secara langsung dianggap praktik buruk pada umumnya.Jadi, Anda perlu menciptakan kembali keseluruhan
parent
objek. Namun dalam hal ini kita akan menemui masalah lain. Bereaksi akan berpikir bahwa semua anak telah mengubah nilai-nilai mereka dan akan membuat ulang semuanya. Tentu saja itu tidak baik untuk kinerja.Masih mungkin untuk menyelesaikan masalah itu dengan menulis beberapa logika yang rumit,
shouldComponentUpdate()
tetapi saya lebih suka berhenti di sini dan menggunakan solusi sederhana dari versi singkat.sumber
Penolakan
jawaban atas kesengsaraan Anda - lihat contoh di sini
Ada cara lain yang lebih singkat untuk memperbarui properti bersarang apa pun.
Pada satu baris
catatan: Ini di sini adalah operator Koma ~ MDN , lihatlah dalam aksi di sini (Kotak Pasir) .
Ini mirip dengan (meskipun ini tidak mengubah referensi keadaan)
Untuk perbedaan halus dalam konteks ini antara
forceUpdate
dansetState
lihat contoh terkait.Tentu saja ini menyalahgunakan beberapa prinsip inti, karena
state
seharusnya hanya-baca, tetapi karena Anda segera membuang negara lama dan menggantinya dengan negara baru, itu sepenuhnya ok.Peringatan
Meskipun komponen yang berisi status akan diperbarui dan dirender ulang dengan benar ( kecuali gotcha ini ) , alat peraga akan gagal disebarkan ke anak-anak (lihat komentar Spymaster di bawah) . Gunakan teknik ini hanya jika Anda tahu apa yang Anda lakukan.
Misalnya, Anda dapat melewati prop datar yang diubah yang diperbarui dan dilewati dengan mudah.
Sekarang meskipun referensi untuk complexNestedProp tidak berubah ( shouldComponentUpdate )
komponen akan dirender ulang setiap kali pembaruan komponen induk, yang merupakan kasus setelah memanggil
this.setState
atauthis.forceUpdate
di induk.Efek dari mutasi negara
Menggunakan negara bersarang dan bermutasi negara secara langsung berbahaya karena objek yang berbeda mungkin terus (sengaja atau tidak) yang berbeda referensi (tua) ke negara dan mungkin tidak selalu tahu kapan harus update (misalnya saat menggunakan
PureComponent
atau jikashouldComponentUpdate
diimplementasikan untuk pulangfalse
) OR adalah dimaksudkan untuk menampilkan data lama seperti pada contoh di bawah ini.Bagaimanapun di sini Anda dapat melihat bahwa
Nested PureChildClass
itu tidak dirender karena alat peraga gagal untuk disebarkan.sumber
state
sepenuhnya dan menggunakan properti kustom yang dapat diamati . React'ssetState
hanyalah kenyamanan bawaan, tetapi Anda segera menyadari bahwa ia memiliki batasnya. Menggunakan properti khusus dan penggunaan cerdasforceUpdate
memberi Anda lebih banyak. Gunakan Observable sebagai ganti status dalam komponen Bereaksi.this.forceUpdate()
atau mengimplementasikan spesifikshouldComponentUpdate
.Jika Anda menggunakan ES2015, Anda memiliki akses ke Object.assign. Anda dapat menggunakannya sebagai berikut untuk memperbarui objek bersarang.
Anda menggabungkan properti yang diperbarui dengan yang sudah ada dan menggunakan objek yang dikembalikan untuk memperbarui keadaan.
Sunting: Menambahkan objek kosong sebagai target ke fungsi tetapkan untuk memastikan status tidak dimutasi secara langsung seperti yang ditunjukkan carkod.
sumber
sumber
property
berisi beberapa properti bersarang, yang pertama akan menghapusnya, yang kedua tidak. codesandbox.io/s/nameless-pine-42thuAda banyak perpustakaan untuk membantu ini. Misalnya, menggunakan pembantu-immutabilitas :
Menggunakan set lodash / fp :
Menggunakan lodash / fp merge:
sumber
lodash
, Anda mungkin ingin mencoba_.cloneDeep
dan mengatur status menjadi salinan yang dikloning.lodash/fp
, jadi kita tidak perlu khawatir tentang mutasi.merge
atauset
fungsi di lodash / fp selain sintaks?this.setState(newState)
metode lodash / fp juga. Gotcha lain adalah bahwa lodash.set
(non-fp) memiliki urutan argumen yang berbeda yang membuat saya tersandung untuk sementara waktu.Kami menggunakan Immer https://github.com/mweststrate/immer untuk menangani masalah seperti ini.
Baru saja mengganti kode ini di salah satu komponen kami
Dengan ini
Dengan immer Anda menangani negara Anda sebagai "objek normal". Keajaiban terjadi di belakang layar dengan objek proxy.
sumber
Berikut variasi jawaban pertama yang diberikan di utas ini yang tidak memerlukan paket tambahan, pustaka, atau fungsi khusus.
Untuk mengatur keadaan bidang bersarang tertentu, Anda telah mengatur seluruh objek. Saya melakukan ini dengan membuat variabel,
newState
dan menyebarkan konten dari kondisi saat ini ke dalamnya terlebih dahulu menggunakan operator penyebaran ES2015 . Kemudian, saya mengganti nilaithis.state.flag
dengan nilai baru (karena saya aturflag: value
setelah saya menyebarkan keadaan saat ini ke objek,flag
bidang dalam keadaan saat ini ditimpa). Lalu, saya cukup mengatur keadaansomeProperty
kenewState
objek saya .sumber
Meskipun bersarang tidak benar-benar bagaimana Anda harus memperlakukan keadaan komponen, kadang-kadang untuk sesuatu yang mudah untuk bersarang tingkat tunggal.
Untuk keadaan seperti ini
Metode re-useable ive digunakan akan terlihat seperti ini.
lalu hanya memasukkan nama objek untuk setiap sarang yang ingin Anda tuju ...
sumber
Saya menggunakan solusi ini.
Jika Anda memiliki status bersarang seperti ini:
Anda dapat mendeklarasikan fungsi handleChange yang menyalin status saat ini dan menetapkan kembali dengan nilai yang diubah
di sini html dengan pendengar acara
sumber
Buat salinan status:
lakukan perubahan pada objek ini:
sekarang perbarui status
sumber
Meskipun Anda bertanya tentang keadaan komponen Bereaksi berbasis kelas, masalah yang sama ada dengan useState hook. Lebih buruk lagi: hook penggunaanState tidak menerima pembaruan parsial. Jadi pertanyaan ini menjadi sangat relevan ketika useState hook diperkenalkan.
Saya telah memutuskan untuk mengirim jawaban berikut untuk memastikan pertanyaannya mencakup skenario yang lebih modern di mana hook useState digunakan:
Jika Anda punya:
Anda dapat mengatur properti bersarang dengan mengkloning arus dan menambal segmen data yang diperlukan, misalnya:
Atau Anda dapat menggunakan perpustakaan Immer untuk menyederhanakan kloning dan menambal objek.
Atau Anda dapat menggunakan pustaka Hookstate (penafian: Saya seorang penulis) untuk sekadar mengelola data negara (global dan global) yang kompleks sepenuhnya dan meningkatkan kinerja (baca: tidak perlu khawatir tentang rendering optimasi):
dapatkan bidang untuk dirender:
setel bidang bersarang:
Berikut ini adalah contoh Hookstate, di mana status bersarang secara mendalam / berulang dalam struktur data seperti pohon .
sumber
Dua opsi lain yang belum disebutkan:
sumber
Untuk membuat semuanya menjadi umum, saya mengerjakan jawaban @ ShubhamKhatri dan @ Qwerty.
nyatakan objek
kontrol input
metode updateState
setState sebagai jawaban @ ShubhamKhatri
setState sebagai jawaban @ Qwerty
Catatan: Metode di atas tidak akan berfungsi untuk array
sumber
Saya menanggapi dengan sangat serius kekhawatiran yang telah disuarakan untuk membuat salinan lengkap status komponen Anda. Dengan itu, saya akan sangat menyarankan Immer .
Ini harus bekerja untuk
React.PureComponent
(yaitu perbandingan keadaan dangkal oleh Bereaksi) karena secaraImmer
cerdik menggunakan objek proxy untuk secara efisien menyalin pohon keadaan jauh yang sewenang-wenang. Immer juga lebih aman dibandingkan pustaka seperti Immutability Helper, dan sangat ideal untuk pengguna Javascript dan naskah.Fungsi utilitas typescript
sumber
sumber
obj
hanya referensi ke negara, jadi melalui itu Anda bermutasithis.state
objek yang sebenarnyaSaya menemukan ini berfungsi untuk saya, memiliki formulir proyek dalam kasus saya di mana misalnya Anda memiliki id, dan nama dan saya lebih suka mempertahankan status untuk proyek bersarang.
Biarkan aku tahu!
sumber
Sesuatu seperti ini mungkin sudah cukup,
sumber
Saya tahu ini adalah pertanyaan lama tetapi masih ingin membagikan bagaimana saya mencapai ini. Dengan asumsi keadaan dalam konstruktor terlihat seperti ini:
handleChange
Fungsi saya seperti ini:Dan pastikan Anda memberi nama input yang sesuai:
sumber
Saya melakukan pembaruan bersarang dengan pencarian yang dikurangi :
Contoh:
Variabel bersarang dalam status:
Fungsi:
Menggunakan:
sumber
Ini adalah status awal saya
Kait atau Anda dapat menggantinya dengan negara (komponen kelas)
Metode untuk handleChange
Metode untuk mengatur kondisi dengan status bersarang
Akhirnya ini adalah input yang saya gunakan
sumber
Jika Anda menggunakan formik dalam proyek Anda, ia memiliki beberapa cara mudah untuk menangani hal ini. Inilah cara termudah untuk melakukannya dengan formik.
Pertama atur nilai awal Anda di dalam atribut initivalues formik atau di reaksi. negara
Di sini, nilai awal didefinisikan dalam keadaan bereaksi
tentukan initialValues di atas untuk bidang formik di dalam
initiValues
atribut formikBuat konsol untuk memeriksa keadaan diperbarui ke dalam
string
bukannya fungsiboolean
formiksetFieldValue
untuk mengatur negara atau pergi dengan alat debugger bereaksi untuk melihat perubahan dalam nilai-nilai status formis iniside.sumber
coba kode ini:
sumber
someProperty
dan setelah kode di atas dijalankan hanyaflag
properti yang akan tetapSaya melihat berikut dalam sebuah buku:
tapi saya tidak yakin apakah itu benar ..
sumber