Saya sedang menulis aplikasi jadual waktu bas yang menggunakan jenis objek untuk memodelkan "dokumen" jadual waktu.
interface Timetable { name: string stops: string[] services: string[][] }
Selain jenis, saya mempunyai banyak fungsi, dan jika saya akan menggunakan mutasi, saya biasanya menulisnya sebagai kaedah di kelas. Saya kebanyakannya menggunakan Immer jadi saya tidak perlu menulis banyak sintaks lanjutan. Contohnya,
const addStop = (timetable: Timetable, stopName: string): Timetable => { return produce(timetable, (newTimetable) => { newTimetable.stops.push(stopName) }) }
Untuk menguruskan keadaan saya menggunakan Zustand dan Immer, tetapi saya rasa jika saya menggunakan Redux masalah saya akan menjadi sama. Di kedai saya, saya mempunyai pelbagai objek Jadual Waktu dan operasi yang turut menggunakan Immer untuk menetapkan semula objek Jadual Waktu yang dipilih sekarang:
updateTt: (tt, index) => { set((state) => { state.timetables[index] = tt }) }, updateThisTt: (timetable) => { set((s) => { if (s.selectedTtIdx === null) { throw new Error("no selected timetable") } s.timetables[s.selectedTtIdx] = timetable }) },
Kemudian saya memanggil fungsi perubahan data dalam komponen React dan memanggil operasi kemas kini:
const onAddStop = (name) => { updateThisTt(addStop(timetable, name)) }
Ini berfungsi, tetapi saya tidak pasti sama ada saya melakukannya dengan betul. Saya kini mempunyai dua lapisan panggilan Immer, komponen saya kini mempunyai fungsi pengubahsuaian data yang dipanggil terus dalam pengendali acaranya, dan saya tidak begitu menyukai rupa "kaedah" walaupun ia adalah pepijat kecil secara keseluruhan.
Saya menganggap:
Timetable
类型转换为一个类,将数据修改函数重写为变异方法,并设置 [immerable] = true
saya dan biarkan Immer melakukan semua kerja untuk tindakan saya. Saya telah melakukan ini, tetapi saya lebih suka berpegang pada mod rekod tidak berubah. Untuk nilainya, dokumentasi untuk Flux, Zustand atau Immer cenderung menunjukkan pilihan pertama, dan hanya sekali-sekala tiada aplikasi semudah counter = counter + 1
. Apakah cara terbaik untuk membina aplikasi menggunakan seni bina Flux?
(Saya tidak biasa dengan Zusand dan Immer, tetapi mungkin saya boleh membantu...)
Selalu ada cara yang berbeza dan saya mencadangkan cara kegemaran saya di sini.
Bezakan dengan jelas antara tindakan "penjadualan" dan "mutasi" sebenar keadaan. (Mungkintambah tahap lain di antaranya).
Fungsi "Mutasi" khusus
Saya syorkan mencipta khusus fungsi "mutasi" dan bukannya yang generik, iaitu:
updateThisTt:() => { ...
,addStop: () => { ...
.Buat seberapa banyak fungsi mutasi yang anda perlukan, setiap satu dengan tujuan.
Bina keadaan baharu dalam fungsi "mutasi"
Secara konsep, hanya gunakan
immer
penjana di dalam fungsi mutasi.(Maksud saya tentang kedai. Sudah tentu, anda masih boleh menggunakan
immer
untuk tujuan lain) .Berdasarkan contoh rasmi ini :
Di dalam komponen anda kini boleh memanggil fungsi "mutator".
Membina negara baharu
Jika membina keadaan baharu menjadi rumit, anda masih boleh mengekstrak beberapa fungsi "pembina". Tetapi mula-mula pertimbangkan bahagian seterusnya, "Fail Besar dan Penduaan."
Sebagai contoh, fungsi
addStop
anda juga boleh dipanggil dalam mutasi Zustand:Fail besar dan pendua
Penduaan kod pastinya harus dielakkan, tetapi sentiasa ada pertukaran.
Saya tidak akan mencadangkan pendekatan khusus, tetapi ambil perhatian bahawa kod selalunya lebih banyak dibaca daripada ditulis. Kadang-kadangSaya rasa patut menulis beberapa huruf lagi, seperti sesuatu seperti
state.timetables[index]
beberapa kali, Jika ia menjadikan tujuan kod lebih jelas. Anda perlu menilai sendiri.Apa pun, saya syorkan meletakkan fungsi mutasi anda ke dalam fail berasingan yang tidak melakukan apa-apa lagi, Dengan cara ini, ia mungkin kelihatan lebih mudah untuk difahami daripada yang anda fikirkan.
Jika anda mempunyai fail yang sangat besar tetapi tertumpu sepenuhnya hanya pada mengubah suai keadaan , Dan strukturnya adalah konsisten, menjadikannya mudah dibaca walaupun anda perlu menatal Beberapa muka surat.
Sebagai contoh jika ia kelihatan seperti ini:
Juga ambil perhatian bahawa fungsi variadic ini adalah bebas sepenuhnya (atau adakah mereka? Saya harap Zustand telah menggunakan fungsi tulen di sini, bukan?) .
Ini bermakna jika ia menjadi rumit, anda juga boleh membahagikan beberapa fungsi mutasi Pisahkan kepada fail berasingan dalam folder Suka
/store/mutators/timeTable.js
.Tetapi anda boleh melakukannya dengan mudah pada bila-bila masa kemudian.
Bina "payload" ("action caller")
Anda mungkin merasakan keperluan untuk "tahap" lain Antara pengendali peristiwa dan mutator. Saya biasanya mempunyai lapisan seperti ini, tetapi saya tidak mempunyai nama yang baik untuknya. Mari kita rujuk sementara ini sebagai "Pemanggil Operasi".
Kadangkala sukar untuk memutuskan apa itu "variogram" dan apa itu "variogram" "Pemanggil tindakan".
Bagaimanapun anda boleh "membina beberapa data" di dalam "pemanggil tindakan" tetapi anda harus melakukannya Tiada sebarang manipulasi negeri dilakukan di sini , malah dengan
immer
.Mengubah keadaan dan mencipta muatan
Ini adalah perbezaan yang ketara dan anda mungkin tidak perlu terlalu risau tentangnya (dan mungkin terdapat pengecualian) , tetapi sebagai contoh:
Anda boleh menggunakan beberapa bahagian keadaan lama di dalam "pemanggil tindakan", contohnya:
Tetapi anda tidak sepatutnya tidak memetakan (atau mengubah) keadaan lama kepada keadaan baharu, contohnya:
Contoh lain
Tiada cadangan khusus dibuat di sini, hanya contoh:
Menyalurkan banyak nilai kepada mutator boleh mengelirukan, contohnya:
Dalam pengendali acara, anda ingin memberi tumpuan kepada perkara yang anda mahu lakukan, seperti "tambah item baharu", Tetapi jangan pertimbangkan semua hujah. Selain itu, anda mungkin memerlukan item baharu untuk perkara lain.
Atau anda boleh menulis: