Setiap pembangun React akhirnya akan menghadapi soalan yang sama: patutkah saya menggunakan Context, atau adakah ini masalah Redux? Jika anda baru membina aplikasi selama beberapa bulan, hingar-bingar di internet membuatkan ia kedengaran seperti keputusan yang mesti dipilih salah satu sahaja. Sesetengah tutorial menganggap Redux sebagai beban lama. Yang lain memberi amaran bahawa Context tidak boleh berkembang melampaui senarai tugasan. Kedua-dua ekstrem ini tidak membantu. Hakikatnya, alatan ini menyelesaikan jenis masalah yang berbeza, dan pilihan yang bijak bergantung pada apa yang sebenarnya dilakukan oleh aplikasi anda.
Masalah Prop Drilling
Sebelum anda memilih strategi pengurusan keadaan (state management), adalah lebih baik untuk memahami "penyakit" yang cuba disembuhkan oleh kedua-dua alatan ini. Bayangkan anda sedang membina laman e-dagang. Anda mengambil profil pengguna pada komponen App peringkat tertinggi. Di bahagian bawah dalam footer, komponen AccountLink yang kecil memerlukan gambar profil tersebut. Tanpa stor global, objek pengguna perlu melalui Home, kemudian Header, kemudian NavContainer, kemudian UserDropdown, dan akhirnya ke dalam AccountLink. Setiap lapisan di antaranya menyentuh data yang tidak digunakannya. Itulah yang dipanggil prop drilling.
Prop drilling menjadikan komponen rapuh. Proses refactoring menjadi berisiko kerana menarik keluar satu "orang tengah" akan memutuskan rantaian tersebut. Kebolehgunaan (reusability) terjejas kerana komponen menuntut props yang hanya mereka hantar ke bawah. Kedua-dua Context dan Redux menghapuskan masalah ini dengan membenarkan komponen yang jauh melanggan data kongsi secara terus. Namun, cara mereka menyampaikan data tersebut, dan kos untuk melakukannya, berbeza dengan cepat.
Bilakah React Context API Adalah Pilihan yang Tepat
React Context dibina di dalam perpustakaan itu sendiri. Tiada pemasangan npm tambahan, tiada konfigurasi binaan, tiada fail boilerplate. Anda mencipta objek context, membungkus sebahagian daripada pokok (tree) anda dalam Provider, dan menggunakan nilai tersebut dengan useContext dalam mana-mana komponen bersarang. Disebabkan kesederhanaan itu, Context menyerlah dalam projek kecil hingga sederhana di mana perubahan keadaan jarang berlaku dan bentuk keadaan tersebut agak mendatar.
Fikirkan tentang tema UI. Seorang pengguna mungkin menukar antara mod terang dan gelap sekali sahaja dalam satu sesi. Nilai tersebut tersebar ke setiap komponen berstail, tetapi ia jarang berubah sehingga kebimbangan prestasi hampir tidak terasa. Status pengesahan (authentication) adalah satu lagi padanan klasik. Sebaik sahaja pengguna log masuk, bendera isAuthenticated dan objek user kekal stabil merentasi puluhan navigasi halaman. Tetapan bahasa atau penyetempatan (localization) berkelakuan dengan cara yang sama. Ini adalah isyarat yang luas dan bergerak perlahan yang diperlukan oleh banyak komponen, tetapi hanya sedikit komponen yang mengubahnya.
Kekangannya adalah bagaimana Context mengendalikan kemas kini. Apabila nilai Context Provider berubah, React akan melakukan render semula pada setiap komponen yang menggunakan context tersebut. Dalam aplikasi kecil, anda tidak akan merasainya. Dalam aplikasi yang lebih besar, jika anda meletakkan data yang berubah dengan pantas di dalam Context yang digunakan secara meluas, anda akan mencetuskan rantaian render yang membazir. Anda boleh membahagikan context untuk mengasingkan ketidaktentuan, tetapi pada tahap itu anda sedang melakukan kerja kejuruteraan manual untuk penyelesaian sementara yang sebenarnya sudah diselesaikan oleh alatan lain.
Bilakah Redux Toolkit Berhak Mendapat Tempatnya
Redux Toolkit direka untuk aplikasi di mana keadaan adalah kompleks, kemas kini kerap berlaku, dan pelbagai ciri yang jauh perlu membaca dan menulis data yang sama tanpa bertembung. Pertimbangkan sebuah troli membeli-belah. Pengguna menambah item daripada kad produk. Ikon troli di bahagian header mesti mengemas kini bilangan lencana. Bar sisi meluncur keluar untuk menunjukkan item baris. Input kod diskaun menjalankan pengesahan. Halaman pembayaran kemudian membaca kandungan troli. Keadaan tersebut disentuh oleh komponen yang tidak berkaitan di seluruh pokok aplikasi, dan ia kerap berubah.
Redux Toolkit menyelesaikan masalah ini melalui stor berpusat dan bahagian (slices) keadaan yang eksplisit. Komponen hanya melanggan cebisan data yang mereka perlukan menggunakan useSelector. Jika harga stok dikemas kini dalam papan pemuka masa nyata, komponen yang memaparkan tetapan profil pengguna tidak akan terganggu. Redux menggunakan semakan kesamaan rujukan di sebalik tabir supaya langganan adalah terperinci. Ini menjadi kritikal apabila jumlah komponen anda meningkat kepada ratusan.
Redux juga memberi anda aliran data yang boleh diramal. Perubahan keadaan berlaku melalui tindakan (actions) yang dihantar dan dikendalikan oleh reducer. Ia kedengaran seperti jargon, tetapi dalam praktiknya, ini bermakna anda boleh mencari addToCart dalam kod anda menggunakan grep dan menemui setiap laluan kod yang mengubah troli tersebut. Dalam pasukan yang besar, kontrak itu dapat mengelakkan pepijat. Sebaliknya, Context hanyalah satu nilai dan satu setter. Mana-mana pengguna boleh memanggil setState, dan untuk mengesan punca nilai yang salah bermakna anda perlu meletakkan breakpoint di pelbagai komponen.
Di Mana Mereka Benar-benar Berbeza
Ciri-ciri prestasi membezakan alat-alat ini lebih daripada apa pun yang lain. Context menyiarkan nilai baharu kepada semua pengguna tanpa syarat. Redux hanya memaklumkan pelanggan yang bahagian (slice) terpilihnya telah berubah. Jika anda membina papan pemuka saham masa nyata di mana sebut harga dikemas kini setiap saat, Context akan memaksa "re-render" global secara besar-besaran. Redux pula hanya akan membenarkan sel penunjuk (ticker cell) dan carta sparkline dikira semula.
Debugging adalah satu lagi bidang di mana Redux mengatasi pesaingnya dalam aplikasi yang kompleks. Redux DevTools memberikan anda keupayaan debugging "time-travel". Anda boleh melangkah ke belakang melalui setiap tindakan (action) yang dihantar dan melihat keadaan (state) diputar balik. Dalam aliran daftar keluar berbilang langkah dengan pengiraan penghantaran, pengesahan pembayaran, dan pemulihan ralat, keupayaan untuk memainkan semula urutan tepat yang menyebabkan pepijat adalah sangat berharga. Context bergantung kepada React DevTools standard. Anda boleh memeriksa nilai context semasa, tetapi tiada log tindakan terbina dalam atau paparan perbezaan (diff) state. Anda terpaksa kembali menggunakan console.log.
Middleware dan kesan sampingan adalah sebahagian daripada DNA Redux. Redux Toolkit menyertakan createAsyncThunk dan menyepadukan dengan kemas bersama perpustakaan pengambilan data (data-fetching libraries). Anda boleh menyelaraskan panggilan API, memaparkan penunjuk pemuatan (loading spinner), mengendalikan kegagalan rangkaian, dan menyimpan cache keputusan, semuanya dalam aliran data Redux. Context tidak menawarkan corak terbina dalam untuk logik asinkronus. Anda sama ada mengambil data di dalam komponen dan kemudian menolak hasilnya ke dalam Context, atau anda membungkus provider dalam utiliti asinkronus buatan sendiri. Itu boleh berfungsi, tetapi ia bersifat ad hoc.
Kos penyediaan adalah di mana Context menang dengan mudah. Ia mengambil masa kira-kira lima minit untuk membina provider tema. Redux Toolkit memerlukan penciptaan fail store, pendefinisian slice, dan pembungkusan aplikasi anda dalam satu Provider. Ia bukan lagi proses yang memakan masa seminggu seperti Redux lama dengan timbunan kod boilerplate, tetapi ia masih memerlukan lebih banyak penyediaan berbanding Context. Untuk projek sampingan hujung minggu atau papan pemuka dengan tiga laluan (routes), beban kerja (overhead) tersebut mungkin tidak berbaloi.
Menggunakan Kedua-duanya dalam Aplikasi yang Sama
Anda tidak perlu memilih satu pihak sahaja. Banyak aplikasi pengeluaran menggunakan Context untuk urusan kerangka UI global dan Redux untuk data perniagaan yang berat dengan domain. Corak yang biasa adalah untuk menyimpan tema, lokal (locale), dan mungkin bendera pengesahan (auth flag) yang ringan dalam Context kerana setiap laluan memerlukannya dan ia jarang berubah. Sementara itu, sistem pengurusan pesanan, pusat pemberitahuan, dan jadual data berada dalam Redux di mana kemas kini yang kerap dan logik merentas komponen memerlukan kawalan yang tepat.
Pendekatan hibrid ini mengekalkan perkara mudah agar kekal mudah tanpa memaksa penggunaan store Redux yang lengkap untuk objek tema yang statik. Ia juga menghalang slice Redux anda daripada dipenuhi dengan elemen UI yang sebenarnya tidak memerlukan pengurusan state gred industri sejak awal lagi.
Kesimpulan Sebenar
Tiada kebanggaan dalam memilih alat yang lebih berat. Mulakan dengan melihat kekerapan state anda berubah, berapa banyak komponen yang menyentuhnya, dan sama ada anda perlu menjejaki mutasi merentas sempadan pasukan. Jika anda menguruskan nilai yang jarang berubah dan dikongsi secara meluas dalam aplikasi bersaiz sederhana, Context mungkin sudah mencukupi. Jika state anda kerap berubah, merangkumi ciri-ciri yang tidak berkaitan, dan memerlukan jejak audit yang jelas, Redux Toolkit akan menyelamatkan anda daripada kesulitan.
Pilih berdasarkan bentuk projek anda, bukan berdasarkan ceramah persidangan atau bintang GitHub. Troli membeli-belah yang mencapai lima puluh item tidak secara automatik memerlukan Redux, dan suis tema tidak memerlukan store global. Padankan alat dengan masalah, dan kod anda akan kekal mudah diselenggara lama selepas kitaran hype berakhir.
