Redux: Pertanyaan: Bagaimana cara memilih antara toko Redux dan status React?

Dibuat pada 27 Jan 2016  ·  26Komentar  ·  Sumber: reduxjs/redux

question

Komentar yang paling membantu

Gunakan React untuk keadaan singkat yang tidak penting bagi aplikasi secara global dan tidak bermutasi dengan cara yang rumit. Misalnya, tombol beralih di beberapa elemen UI, status input formulir. Gunakan Redux untuk status yang penting secara global atau dimutasi dengan cara yang kompleks. Misalnya, pengguna yang disimpan dalam cache, atau draf posting.

Terkadang Anda ingin berpindah dari status Redux ke status React (saat menyimpan sesuatu di Redux menjadi canggung) atau sebaliknya (saat lebih banyak komponen perlu memiliki akses ke beberapa status yang dulunya lokal).

Aturan praktisnya adalah: lakukan apa pun yang tidak terlalu canggung.

Semua 26 komentar

Gunakan React untuk keadaan singkat yang tidak penting bagi aplikasi secara global dan tidak bermutasi dengan cara yang rumit. Misalnya, tombol beralih di beberapa elemen UI, status input formulir. Gunakan Redux untuk status yang penting secara global atau dimutasi dengan cara yang kompleks. Misalnya, pengguna yang disimpan dalam cache, atau draf posting.

Terkadang Anda ingin berpindah dari status Redux ke status React (saat menyimpan sesuatu di Redux menjadi canggung) atau sebaliknya (saat lebih banyak komponen perlu memiliki akses ke beberapa status yang dulunya lokal).

Aturan praktisnya adalah: lakukan apa pun yang tidak terlalu canggung.

Untuk data yang diambil melalui permintaan jaringan, selalu gunakan penyimpanan untuk mendukung rendering sisi server (jika Anda yakin itu adalah tujuan akhir), atau Anda tidak akan dapat melakukan rehidrasi.

Untuk negara bagian itu untuk didengarkan oleh dua atau lebih kontainer, itu juga harus di toko?

Saya setuju dengan @gaeron tentang perbedaan singkat vs. persisten. Tapi saya sebenarnya memikirkan ini dalam tiga kategori . Salah satunya adalah UI yang dia bicarakan dan saya juga menganggapnya fana. Lainnya adalah status aplikasi yang sebenarnya merupakan inti aplikasi yang persisten. Tetapi yang ketiga, yang berada di antara keduanya, adalah status perutean . Saya menggunakan istilah "perutean" karena istilah tersebut familier bagi orang-orang, tetapi saya mengabstraksi ini menjadi status "pilihan tampilan" karena menurut saya itu mencakup desktop, web, dan seluler dengan lebih baik.

Sekarang Anda dapat berargumen bahwa ini adalah status UI karena menentukan apa yang dilihat orang (seperti status tab, misalnya). Tetapi saya melihat dua perbedaan. Yang pertama adalah bahwa negara dibuat berseri (yaitu, sebagai URL) dan dikirim ke orang lain. Jadi semuanya harus masuk dalam status rute jika Anda ingin orang-orang dapat "menautkan dalam" langsung ke status UI tertentu tersebut . Yang kedua adalah bahwa dalam banyak kasus status rute awal atau perubahan rute memicu perubahan status aplikasi (misalnya, memuat data untuk dilihat). Tentu saja, tindakan di UI melakukan hal yang sama. Tetapi perbedaan yang saya buat adalah bahwa Anda dapat (dan harus) memiliki status rute tanpa melihat atau merender secara tepat untuk menguji "logika aplikasi" di sekitar perubahan status rute. Dan itu karena tampilan dan rendering tidak perlu terlibat yang menjadikannya sebagian dari status aplikasi, IMHO.

Bagaimana ini berhubungan dengan pertanyaan tentang Redux vs. React untuk manajemen negara? Status aplikasi adalah domain Redux dan status UI adalah domain React. Tetapi status perutean harus (menurut saya) dikelola oleh Redux meskipun dapat dilihat sebagai status UI (lihat tautan yang disematkan untuk diskusi lebih lanjut tentang mengapa saya berpikir demikian).

Supaya jelas, komentar @gaearon tentang hal-hal yang berpindah-pindah masih berlaku. Tetapi saya hanya merasa berguna untuk membedakan kasus-kasus yang berbeda ini.

Status aplikasi adalah domain Redux dan status UI adalah domain React.

Perhatikan bahwa saya tidak mengklaim ini. Saya pikir tidak masalah untuk mempertahankan beberapa status aplikasi di React, dan beberapa status UI di Redux. Saya tidak berpikir mereka harus dipisahkan oleh domain.

Cara saya memikirkannya, jika Anda membuat aplikasi dengan Redux, gunakan pohon status tunggal. Letakkan juga status UI di sana. Namun jika membosankan dan membuat frustrasi jangan takut untuk memasukkan status ke dalam komponen. Maksud saya adalah menggunakan pohon status tunggal kecuali jika canggung, dan hanya melakukan ini ketika menyederhanakan hal-hal untuk Anda daripada memperumitnya. Itulah satu-satunya pedoman.

Pertama, saya tentu tidak bermaksud untuk mengucapkan kata-kata di mulut @gaearon , maaf untuk itu.

Kedua, saya sepenuhnya setuju dengan @gaearon. Saya juga sangat percaya pada pendekatan pohon negara tunggal. Ketika saya berbicara tentang status UI, saya memikirkan hal-hal yang sangat kecil (seperti apa yang dipilih tab saat ini) di mana mungkin tidak terlalu relevan dengan status aplikasi (persis seperti yang dibahas

Jadi izinkan saya menjelaskan posisi saya. Saya setuju bahwa hampir semuanya harus ada di Redux , termasuk status rute (seperti yang telah saya lakukan dalam implementasi TodoMVC saya dengan Redux dan TypeScript . Saya secara khusus menyebutkan status rute dan membedakannya karena menurut saya (dan Anda dapat melihatnya di TodoMVC itu) implementasi) yang pasti milik Redux (dan tidak boleh terhubung sama sekali untuk rendering) dan yang paling pasti bukan "status UI".

Untuk komponen React saya jarang menggunakan state. Saya lebih suka menggunakan props untuk mendapatkan informasi tentang apa yang harus dirender dan untuk mendapatkan penutupan yang dapat saya panggil untuk memicu perubahan di luar komponen saya. Ada beberapa keadaan yang jarang terjadi di mana saya memperkenalkan status dalam komponen hanya untuk membuat hidup lebih mudah, tetapi saya mencoba menghindarinya. Saya harap itu menjelaskan banyak hal.

Saya pikir pertanyaan ini sangat subjektif dan rumit, jadi saya membuat keputusan sulit dengan tim saya hari ini, jangan repot-repot:

  • untuk wadah yang tidak dapat digunakan kembali, yang memiliki koneksi ke Redux, masukkan saja semuanya ke toko Redux, bahkan status UI kecil seperti jika modal terbuka, jangan gunakan this.setState lagi.
  • untuk komponen yang dapat digunakan kembali, yang tidak ada hubungannya dengan Redux, gunakan status React.

Dan sekarang kami menerapkan beberapa pembantu untuk mengurangi beban dalam mengelola status UI yang kecil.

@gaearon @ lionng429 @xogeny Ada kelemahan yang dapat Anda pikirkan tentang pendekatan ini?

@inetfuture Saya cenderung agak kikir tentang status aplikasi (redux) karena saya menggunakan TypeScript dan saya mendefinisikan tipe untuk status aplikasi saya sepenuhnya. Karena itu, saya mendapat kejadian saat mengembangkan pustaka komponen untuk memisahkan semua manipulasi status dari rendering (lihat tautan di komentar sebelumnya untuk lebih jelasnya). Ini berarti bahwa bahkan untuk komponen umum yang tidak sepele, saya benar-benar mengeluarkan status. Saya biasanya melewatkan semuanya melalui props (baik state dan closure untuk memanipulasi state). Dengan begitu, saya dapat dengan mudah mengaitkannya ke status aplikasi saya. Bagian dari ini tidak diragukan lagi merupakan artefak menggunakan TypeScript dan tidak dapat hanya menggunakan combineReducers dan connect untuk menghubungkan semuanya (dan setidaknya mempertahankan batasan jenis). Jadi ini mungkin bukan sudut pandang yang representatif. Tetapi saya akan mengatakan bahwa mengapa Anda mengatakan "masukkan saja semuanya ke toko Redux", saya khawatir Anda akan berakhir dengan bak cuci piring negara. Saya pikir fakta bahwa penggunaan TypeScript saya berarti bahwa diperlukan upaya untuk memperluas status aplikasi tidak selalu merupakan hal yang buruk karena memaksa saya untuk memutuskan "apakah saya benar-benar membutuhkan ini?" alih-alih membiarkan barang-barang menumpuk.

Sebagai pemikiran alternatif: status komponen lokal dapat berguna untuk input terkontrol yang memerlukan waktu pembaruan cepat, serta mengurangi jumlah tindakan aktual yang dipicu. Dalam prototipe saya saat ini, saya mengumpulkan HOC pengeditan formulir yang menerima item saat ini yang sedang diedit sebagai properti. Ini juga menangani peristiwa perubahan masukan formulir dengan menyimpan kolom yang diubah dalam statusnya, lalu memanggil pembuat tindakan "EDIT_ITEM_ATTRIBUTE" yang tidak dapat dibaca dengan gabungan perubahan WIP lokal. Hasilnya adalah kolom formulir segera diperbarui, karena hanya formulir itu sendiri yang dirender ulang, dan tindakan yang dipicu jauh lebih sedikit (seperti, jika saya menahan 'A' selama beberapa detik, hanya nilai 'AAAAAAAAAAAA' yang akan dikirim sebagai tindakan alih-alih 'A', 'AA', dll).

Saya telah mendapatkan HOC sebagai intinya di https://gist.github.com/markerikson/554cab15d83fd994dfab , jika ada yang peduli.

Bagaimanapun, intinya adalah bahwa status komponen dan status penyimpanan sama-sama memiliki kegunaan - Anda hanya perlu mempertimbangkan kasus penggunaan Anda yang sebenarnya.

Adapun komponen yang dapat digunakan kembali, jika mereka besar dan cukup kompleks, akan cukup bukti di masa depan untuk memiliki status mereka di Redux, terutama untuk ketertelusuran dan pemutaran ulang untuk pengujian. Tetapi masih ada beberapa keraguan tentang bagaimana tepatnya penggunaan ulang kode ini harus dirancang (komponen plus tindakan plus reduksi).

Dalam aplikasi kami, kami memecahkan masalah ini dengan gaya seperti koneksi. https://github.com/Babo-Ltd/redux-state

Saya jarang merasa canggung untuk menyimpan negara bagian di Redux. Saya suka kekuatan yang diberikannya, bahwa di masa mendatang saya dapat membuatnya berinteraksi dengan beberapa komponen lain jika saya membutuhkannya.

Satu-satunya hal yang terlintas di benak saya yang akan menjadi canggung adalah menangani keadaan elemen bentuk, karena jumlahnya bisa sangat banyak. Dalam hal ini saya menggunakan perpustakaan seperti bentuk redux .

Maksud saya adalah menggunakan pohon status tunggal kecuali jika canggung, dan hanya melakukan ini ketika menyederhanakan hal-hal untuk Anda daripada memperumitnya. Itulah satu-satunya pedoman

@gaearon Apakah Anda ingin berbagi pengalaman tentang cara memutuskan kapan atau bagaimana hal itu dianggap _awkward_? Sebagai contoh, dapatkah Anda memberikan beberapa skenario / contoh khas yang menurut Anda cukup canggung jika diletakkan di application state atom? Terima kasih sebelumnya!

@idavollen saya bisa memberikan pasangan:

  • status buka / tutup dropdown, jika tidak, Anda harus melacak semua komponen dropdown di toko Anda
  • ketika Anda membatalkan perubahan <input> , Anda dapat menggunakan status untuk memperbarui nilai secara instan (dan Anda tidak mempertaruhkan komponen lain untuk merender ulang secara tidak perlu) dan memperbarui penyimpanan dengan cara yang tidak perlu

Pada dasarnya Anda harus menggunakannya untuk keadaan yang tidak mempengaruhi komponen lain.

Saya memiliki situasi ketiga untuk dipertimbangkan, misalnya, saya memiliki formulir (komponen wadah reaksi yang memiliki perhitungan mahal dalam metode render) yang terdiri dari banyak baris dengan kotak centang diawali dan tombol kirim. Ketika tombol kirim diklik, formulir harus mengirimkan baris yang kotak centangnya dicentang, yang berarti status sementara dari kotak centang individu sebelum mengirimkan formulir ketika pengguna beralih itu tidak penting dan tidak boleh diperlakukan sebagai status komponen dan beralihnya kotak centang tidak boleh menyebabkan render () untuk dipanggil.

Untuk saat ini, saya tidak akan menempatkan status kotak centang di atom status aplikasi, atau dalam status komponen lokal, yaitu komponen reaksi bentuk untuk menghindari pemanggilan render () yang tidak diperlukan saat mengaktifkan kotak centang, sebaliknya, a Variabel instance lebih disukai untuk menahan kotak centang yang dicentang, namun itu bertentangan dengan pola reaksi.

Saya bertanya-tanya apa pendekatan terbaik untuk mengelola status kotak centang ini dalam kasus ini?

@idavollen apakah kotak centang itu tidak terkontrol ? Jika tidak, Anda tetap merendernya kembali, sehingga Anda dapat melacak mana yang dipilih dalam status komponen dan menggunakannya untuk memilih bagian mana dari data yang akan dikirim.

Seberapa cepat Redux dibandingkan dengan status komponen? Haruskah saya mengandalkan Redux untuk props UI yang benar-benar masuk akal dalam hal pengaturan waktu antara acara aktual dan proses rendering? Saya memiliki situasi yang rumit di mana menggunakan status komponen akan membutuhkan banyak komunikasi yang tidak begitu lurus ke depan. Bantuan apa pun dalam masalah ini akan sangat dihargai.

@tiberiumaxim Dalam pengalaman saya (saya mengembangkan aplikasi dalam react dan redux yang berjalan pada perangkat bertenaga rendah seperti Smart TV). Dalam kebanyakan kasus, memperbarui status komponen akan lebih berkinerja, hanya karena perbedaan yang perlu terjadi ada pada kumpulan data yang lebih kecil dan tidak ada pengiriman yang perlu terjadi. Dalam kasus di mana hanya komponen atau turunan yang memerlukan akses ke status itu, akan lebih baik untuk tetap menggunakan status komponen lokal dan ini sering kali terjadi dengan status terkait UI, namun jika Anda perlu menyimpan data tersebut ke penyimpanan redux di beberapa titik - Anda mungkin perlu menggunakan kombinasi status lokal (komponen) vs global (redux) dan memastikan Anda menyimpan data tersebut ke penyimpanan redux pada waktu yang tepat - yaitu saat pengguna menavigasi keluar dari halaman - atau sesuatu ke efek tersebut. Mungkin jika Anda dapat menjelaskan lebih banyak tentang kasus spesifik Anda - saya dapat memberi Anda informasi yang lebih detail

Terserah Anda untuk memutuskan status apa yang berlaku di Redux, dan apa yang tetap lokal untuk suatu komponen. Anda mungkin ingin membaca http://redux.js.org/docs/faq/OrganizingState.html#organizing -state-only-redux-state dan http://redux.js.org/docs/faq/Performance. html # performance -scaling untuk beberapa informasi terkait.

@deowk terima kasih telah berbagi pengetahuan Anda tentang masalah kinerja, saya pikir sama tetapi perlu konfirmasi.
Juga, @markerikson terima kasih atas

Tidak yakin apakah ada yang menyebutkannya secara eksplisit, tetapi status komponen lokal dapat dikelola oleh Redux juga. Anda dapat membuat toko langsung di konstruktor komponen Anda. Penyimpanan lokal ini akan berisi status komponen ini, dan menangani tindakan yang terkait dengan komponen ini (dan turunannya dengan meneruskan fungsi dispatch penyimpanan ini, atau callback yang memanggil fungsi dispatch ) .

Arsitektur ini dapat diimplementasikan secara manual, atau menggunakan beberapa library seperti redux-fractal, redux-ui dan sebagainya.

Atau, seperti yang ditunjukkan Dan, Anda bahkan dapat menerapkan pendekatan gaya peredam untuk memperbarui status komponen juga! Lihat https://twitter.com/dan_abramov/status/736310245945933824

Saya ingin tahu di mana menyimpan status UI seperti indikator aktivitas dan modal buka atau tutup. Apakah menggunakan setState menyebabkan masalah dalam pengujian unit komponen react?

@ akshay2604 : sekali lagi, itu terserah Anda. Lihat tautan yang saya posting di komentar sebelumnya di utas ini. Anda pasti dapat menggunakan setState saat menguji komponen, terutama jika Anda menggunakan pustaka Enzim untuk membantu mengujinya.

Izinkan saya membagikan pemikiran saya.

Saya mengkategorikan negara menjadi 3 kategori besar menurut bagaimana itu terkait dengan input / output aplikasi:

  • "cache": keadaan yang merupakan cermin dari data persisten. Contoh:
{ "todos": [{ id: 1, title: "title" }, { id: 2, title: "title" }] }
  • "perubahan": keadaan yang mendeskripsikan perubahan tertunda pada data yang persisten. Contoh:
{ "changeTodo": { title: "title", action: "add", done: false },
{ id: 1, title: "changed title", action: "modify", done: true }, { id: 2, action: "delete" } }
  • "view": keadaan yang menyampaikan opsi tampilan seperti pemfilteran saat ini, pengurutan, dll. Contoh:
{ "displayOptions": { searchTerm: "title", sort: ["title", "desc"], filter: "done=false" } }

Anda tidak mencampur cache dengan changes , Anda tidak mencampur cache dengan view , Anda tidak mencampur view dengan changes .

Tentu saja Anda perlu menggabungkan ini entah bagaimana untuk menampilkannya dalam satu komponen react. Sehingga objek "gabungan" Anda menjadi:

{ "todos": [{id: undefined, title: "title", done: false }, { id: 1, title: "changed title" }] }

Tapi itu bukan status, ini hasil dari logika aplikasi Anda. Jadi sebaiknya Anda tidak menyimpannya di mana pun.
Anda dapat menyimpan status gabungan ini di pemilih, Anda dapat menyimpannya di penyimpanan, Anda dapat menyimpannya dalam komponen, tetapi ini bukan "status", itu tidak penting, Anda dapat dengan mudah menerapkan kembali fungsi logika aplikasi Anda ke semua 3 bagian status dan dapatkan status gabungan lagi. Itulah inti dari pendekatan fungsional.

Pengelola Redux akan memberi tahu Anda "Hai, Anda harus menerapkan logika aplikasi Anda sebagai beberapa reduksi dan beberapa peristiwa, yang akan membuat bagian berbeda dari objek" gabungan "Anda."
Saya pikir itu pendekatan yang salah. Itu berarti Anda tidak akan bisa lepas dari redux. Apa yang dimaksudkan sebagai alat untuk mengelola status Anda pada dasarnya menjadi implementasi logika aplikasi Anda.

Hai, Saya menggali React / Redux selama beberapa hari, memahami keputusan yang dibuat untuk memilih apakah beberapa info harus dipromosikan untuk disimpan atau disimpan dalam status lokal komponen.

Tetapi bagaimana jika 1 tindakan membutuhkan keduanya secara bersamaan? Berikut adalah kasus penggunaan, yang sangat umum:

  1. [konteks] Toko Redux adalah satu daun { modelItems: myModelItems } . Ini cache (bagian dari / proyeksi) model server
  2. [konteks] Tampilan dibuat dari satu komponen pintar MyItemsView yang menampilkan daftar UI dari item yang disimpan / di-cache. Saat dipasang, komponen memicu pengambilan item model. Input komponen: myModelItems . Output komponen: pemicu aksi fetchModelItems . Komponen internal: state.busy dan state.errorId
  3. [plan] Ketika MyItemsView memicu fetchModelItems , permintaan HTTP dikirim ke server untuk mengambil model dan menyimpannya dalam cache. Tindakan asinkron ini memiliki 4 fase dan banyak kait: onStarted (Permintaan HTTP akan lepas landas, pemintal pemuatan dimulai di komponen), onEnded (respons HTTP mendarat, pemintalan pemuatan berhenti di komponen , seseorang masih tidak melihat status tanggapan), onFailed (pemberitahuan kesalahan ditampilkan dalam komponen) dan onSucceed (penyimpanan Redux diperbarui kemudian model-cache yang dimilikinya diteruskan ke komponen untuk rendering)

Oleh karena itu, cara membagi pemicu tindakan fetchModelItems sehingga:

  • onStarted , onEnded dan onFailed tidak masuk ke toko Redux? Ini karena onStarted dan onEnded adalah status UI sementara yang seharusnya tidak memiliki interaksi dengan model-cache. Hal yang sama berlaku untuk onFailed (model-cache tetap tidak berubah dan UI akan membuat pemberitahuan kesalahan). MyItemsView akan membuat status-UI di sini, bukan model-cache
  • onSucceed masuk ke toko Redux? Ini karena ia memenangkan lotere model-cache, diberikan akses ke sumber kebenaran, akan mandi dan rehidrasi, kemudian akan menghasilkan myModelItems dalam MyItemsView

Tentang implementasi dalam upaya saya saat ini, Redux Thunk menangani pemicu aksi fetchModelItems . Saya merasa seperti saya memilih jalur Redux di sana, dan saya tidak dapat mengubah pikiran saya lagi untuk mengatakan "teruskan saja keberhasilan asinkron ke penyimpanan Redux, simpan yang lain dalam status komponen React".

Bingung dengan ini, saya mengambil keberhasilan untuk disimpan, yang meneruskan ke komponen yang terhubung (yaitu wadah Redux). Tapi tidak ada pemintal pemuatan dan atm pesan kesalahan log konsol yang menyedihkan. Saya tidak ingin mendefinisikan store.ui.myItemsView.busy atau store.ui.myItemsView.errorId , tetapi hanya mendapatkan info tersebut di status komponen.

@pascav :
Ini adalah pelacak bug, bukan sistem pendukung. Untuk pertanyaan penggunaan, silakan gunakan Stack Overflow atau Reactiflux di mana ada lebih banyak orang yang siap membantu Anda - Anda mungkin akan mendapatkan jawaban yang lebih baik dengan lebih cepat. Terima kasih!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat