Saya menggunakan Redux untuk manajemen negara.
Bagaimana cara mereset toko ke keadaan awal?
Sebagai contoh, katakanlah saya memiliki dua akun pengguna ( u1
dan u2
).
Bayangkan urutan kejadian berikut:
Pengguna
u1
masuk ke aplikasi dan melakukan sesuatu, jadi kami menyimpan beberapa data di toko.Pengguna
u1
keluar.Pengguna
u2
masuk ke aplikasi tanpa menyegarkan peramban.
Pada titik ini, data yang di-cache akan dikaitkan dengan u1
, dan saya ingin membersihkannya.
Bagaimana saya bisa mereset toko Redux ke keadaan awal ketika pengguna pertama log out?
Jawaban:
Salah satu cara untuk melakukannya adalah dengan menulis peredam root di aplikasi Anda.
Root reducer biasanya akan mendelegasikan penanganan aksi ke reducer yang dihasilkan oleh
combineReducers()
. Namun, setiap kali ia menerimaUSER_LOGOUT
tindakan, ia mengembalikan keadaan awal dari awal lagi.Misalnya, jika peredam root Anda terlihat seperti ini:
Anda dapat mengubah nama
appReducer
dan menulisrootReducer
delegasi baru untuk itu:Sekarang kita hanya perlu mengajarkan yang baru
rootReducer
untuk mengembalikan keadaan awal setelahUSER_LOGOUT
tindakan. Seperti yang kita ketahui, reduksi seharusnya mengembalikan keadaan awal ketika mereka dipanggil denganundefined
argumen pertama, apa pun tindakannya. Mari kita gunakan fakta ini untuk menghapus secara akumulatif akumulasi yangstate
kita berikanappReducer
:Sekarang, setiap kali
USER_LOGOUT
kebakaran, semua reduksi akan diinisialisasi lagi. Mereka juga dapat mengembalikan sesuatu yang berbeda dari yang mereka lakukan pada awalnya jika mereka mau karena mereka dapat memeriksaaction.type
juga.Untuk mengulangi, kode lengkap baru terlihat seperti ini:
Perhatikan bahwa saya tidak mengubah keadaan di sini, saya hanya menetapkan ulang referensi variabel lokal yang dipanggil
state
sebelum meneruskannya ke fungsi lain. Mutasi objek negara akan melanggar prinsip Redux.Jika Anda menggunakan redux-persist , Anda mungkin juga perlu membersihkan penyimpanan Anda. Redux-persist menyimpan salinan status Anda di mesin penyimpanan, dan salinan status akan dimuat dari sana saat refresh.
Pertama, Anda perlu mengimpor mesin penyimpanan yang sesuai dan kemudian, untuk menguraikan status sebelum mengaturnya
undefined
dan membersihkan setiap kunci status penyimpanan.sumber
case 'CLEAR_DATA': return initialState
export const createRootReducer = asyncReducers => { const appReducer = combineReducers({ myReducer ...asyncReducers }); return (state, action) => { if (action.type === 'LOGOUT_USER') { state = undefined; } return appReducer(state, action); } };
if (action.type === 'RESET') return action.stateFromLocalStorage
USER_LOGOUT
aksi telah dipecat, apakah mungkin untuk mendapatkan data negara dari sebelumnya? (mis. via devtools)Saya ingin menunjukkan bahwa komentar yang diterima oleh Dan Abramov benar kecuali kami mengalami masalah aneh ketika menggunakan paket react-router-redux bersama dengan pendekatan ini. Perbaikan kami adalah untuk tidak mengatur keadaan,
undefined
tetapi masih menggunakan peredam perutean saat ini. Jadi saya akan menyarankan menerapkan solusi di bawah ini jika Anda menggunakan paket inisumber
router
dan TIDAKrounting
combineReducers()
..... Anda jika Anda memilikinyacombineReducers({routing: routingReducer})
akan seperti yang dijelaskan dalam jawabanTentukan tindakan:
Kemudian di setiap reduksi Anda dengan asumsi Anda menggunakan
switch
atauif-else
untuk menangani beberapa tindakan melalui masing-masing reducer. Saya akan mengambil kasing untukswitch
.Dengan cara ini setiap kali Anda memanggil
RESET
tindakan, peredam Anda akan memperbarui toko dengan status default.Sekarang, untuk keluar Anda dapat menangani hal-hal di bawah ini:
Setiap kali pengguna masuk, tanpa peramban peramban. Store akan selalu default.
store.dispatch(RESET_ACTION)
hanya menguraikan ide. Anda kemungkinan besar akan memiliki pembuat tindakan untuk tujuan tersebut. Cara yang jauh lebih baik adalah Anda memilikiLOGOUT_ACTION
.Setelah Anda mengirim ini
LOGOUT_ACTION
. Kemudian middleware kustom dapat mencegat tindakan ini, baik dengan Redux-Saga atau Redux-Thunk. Namun demikian, Anda dapat mengirim tindakan lain 'RESET'. Dengan cara ini penyimpanan dan pengaturan ulang toko akan terjadi secara serempak dan toko Anda akan siap untuk login pengguna lain.sumber
undefined
seperti pada jawaban lainnya. ketika aplikasi Anda mengharapkan pohon negara dan Anda memberikannyaundefined
, hanya ada lebih banyak bug dan sakit kepala yang harus dihadapi daripada sekadar pohon kosong.Hanya jawaban yang disederhanakan untuk jawaban terbaik:
sumber
Anda juga dapat menjalankan tindakan yang ditangani oleh semua atau beberapa reduksi, yang ingin Anda atur ulang ke penyimpanan awal. Satu tindakan dapat memicu reset ke seluruh negara Anda, atau hanya sebagian yang tampaknya cocok untuk Anda. Saya percaya ini adalah cara paling sederhana dan paling terkendali untuk melakukan ini.
sumber
Dengan Redux jika telah menerapkan solusi berikut, yang mengasumsikan saya telah menetapkan status awal di semua reduksi saya (misalnya {user: {name, email}}). Dalam banyak komponen saya memeriksa properti bersarang ini, jadi dengan perbaikan ini saya mencegah metode rendering saya rusak pada kondisi properti digabungkan (misalnya jika state.user.email, yang akan melempar pengguna kesalahan tidak ditentukan jika solusi yang disebutkan di atas).
sumber
MEMPERBARUI NGRX4
Jika Anda bermigrasi ke NGRX 4, Anda mungkin telah memperhatikan dari panduan migrasi bahwa metode rootreducer untuk menggabungkan reduksi Anda telah diganti dengan metode ActionReducerMap. Pada awalnya, cara baru dalam melakukan sesuatu ini mungkin membuat mengatur ulang keadaan menjadi tantangan. Ini sebenarnya lurus ke depan, namun cara melakukan ini telah berubah.
Solusi ini terinspirasi oleh bagian API meta-reducers dari NGRX4 Github docs.
Pertama, katakanlah Anda menggabungkan pengecil Anda seperti ini menggunakan opsi ActionReducerMap baru NGRX:
Sekarang, katakanlah Anda ingin mengatur ulang status dari dalam app.module `
`
Dan itu pada dasarnya adalah salah satu cara untuk mencapai pengaruh yang sama dengan NGRX 4.
sumber
Menggabungkan pendekatan dari Dan, Ryan dan Rob, untuk memperhitungkan menjaga
router
negara dan menginisialisasi segala sesuatu yang lain di pohon negara, saya berakhir dengan ini:sumber
Saya telah membuat komponen untuk memberikan Redux kemampuan mengatur ulang keadaan, Anda hanya perlu menggunakan komponen ini untuk meningkatkan toko Anda dan mengirimkan tindakan tertentu. Ketik untuk memicu reset. Pikiran implementasi sama dengan apa yang dikatakan @Dan Abramov.
Github: https://github.com/wwayne/redux-reset
sumber
Saya telah membuat tindakan untuk menghapus status. Jadi, ketika saya mengirim pembuat tindakan logout, saya mengirim tindakan untuk menghapus status juga.
Tindakan merekam pengguna
Pembuat tindakan logout
Peredam
Saya tidak yakin apakah ini optimal?
sumber
Jika Anda menggunakan aksi redux , inilah solusi cepat menggunakan HOF ( Fungsi Urutan Tinggi ) untuk
handleActions
.Dan kemudian gunakan
handleActionsEx
alih-alih yang aslihandleActions
untuk menangani reduksi.Jawaban Dan memberi ide bagus tentang masalah ini, tetapi tidak berhasil dengan baik bagi saya, karena saya menggunakan
redux-persist
.Ketika digunakan dengan
redux-persist
, hanya melewatiundefined
status tidak memicu perilaku bertahan, jadi saya tahu saya harus menghapus item secara manual dari penyimpanan (Bereaksi Asli dalam kasus saya, dengan demikianAsyncStorage
).atau
juga tidak bekerja untuk saya - mereka hanya berteriak kepada saya. (mis. mengeluh seperti "Kunci tak terduga _persis ..." )
Lalu tiba-tiba saya merenungkan yang saya inginkan hanyalah membuat setiap peredam individu mengembalikan keadaan awal mereka sendiri ketika
RESET
jenis tindakan ditemui. Dengan begitu, gigih ditangani secara alami. Jelas tanpa fungsi utilitas di atas (handleActionsEx
), kode saya tidak akan terlihat KERING (walaupun itu hanya satu liner, yaituRESET: () => initialState
), tetapi saya tidak tahan karena cuz saya suka metaprogramming.sumber
Solusi berikut ini berhasil untuk saya.
Saya menambahkan pengaturan ulang fungsi negara ke meta reducers. Kuncinya adalah menggunakan
untuk mengatur semua reduksi ke kondisi awal. Kembali
undefined
malah menyebabkan kesalahan karena fakta bahwa struktur toko telah hancur./reducers/index.ts
app.module.ts
sumber
Dari perspektif keamanan, hal paling aman untuk dilakukan ketika login user adalah dengan mengatur ulang semua negara terus-menerus (ex cookies,
localStorage
,IndexedDB
,Web SQL
, dll) dan melakukan refresh keras halaman menggunakanwindow.location.reload()
. Mungkin pengembang yang ceroboh secara tidak sengaja atau sengaja menyimpan beberapa data sensitif padawindow
, di DOM, dll. Menghilangkan semua status persisten dan menyegarkan peramban adalah satu-satunya cara untuk memastikan tidak ada informasi dari pengguna sebelumnya yang bocor ke pengguna berikutnya.(Tentu saja, sebagai pengguna di komputer bersama Anda harus menggunakan mode "penjelajahan pribadi", tutup sendiri jendela peramban, gunakan fungsi "hapus data penjelajahan", dll, tetapi sebagai pengembang, kami tidak dapat mengharapkan setiap orang untuk selalu seperti itu. rajin itu)
sumber
Solusi saya ketika bekerja dengan naskah, dibangun di atas jawaban Dan (pengetikan redux membuatnya tidak mungkin untuk dilewatkan
undefined
ke reducer sebagai argumen pertama, jadi saya cache kondisi root awal dalam konstanta):sumber
Jawaban yang diterima membantu saya menyelesaikan kasus saya. Namun, saya menemukan kasus di mana tidak-seluruh-negara harus dibersihkan. Jadi - saya melakukannya dengan cara ini:
Semoga ini bisa membantu orang lain :)
sumber
Hanya ekstensi untuk jawaban @ dan-abramov , kadang-kadang kita mungkin perlu mempertahankan kunci tertentu agar tidak disetel ulang.
sumber
Opsi cepat dan mudah yang bekerja untuk saya menggunakan redux-reset . Yang mudah dan juga memiliki beberapa opsi lanjutan, untuk aplikasi yang lebih besar.
Setup di buat toko
Kirim 'reset' Anda dalam fungsi logout Anda
Semoga ini membantu
sumber
Saya ambil untuk menjaga Redux dari referensi ke variabel yang sama dari keadaan awal:
sumber
Pendekatan ini sangat tepat: Hancurkan negara "NAME" spesifik untuk mengabaikan dan menjaga orang lain.
sumber
USER_LOGOUT
di peredam itu dan menanganinya di sana.kenapa tidak Anda gunakan saja
return module.exports.default()
;)Catatan: pastikan Anda menetapkan nilai default tindakan
{}
dan Anda OK karena Anda tidak ingin menemukan kesalahan ketika Anda memeriksaaction.type
di dalam pernyataan switch.sumber
Saya menemukan bahwa jawaban yang diterima bekerja dengan baik untuk saya, tetapi memicu
no-param-reassign
kesalahan ESLint - https://eslint.org/docs/rules/no-param-reassignInilah cara saya menanganinya, memastikan untuk membuat salinan negara (yang, dalam pemahaman saya, hal yang harus dilakukan Reduxy ...):
Tapi mungkin membuat salinan negara untuk hanya meneruskannya ke fungsi peredam lain yang membuat salinan yang sedikit terlalu rumit? Ini tidak dibaca dengan baik, tetapi lebih penting:
sumber
Selain jawaban Dan Abramov, seharusnya kita tidak menetapkan tindakan secara eksplisit sebagai action = {type: '@@ INIT'} di samping state = undefined. Dengan jenis tindakan di atas, setiap peredam mengembalikan keadaan awal.
sumber
di server, saya punya variabel: global.isSsr = true dan di setiap reducer, saya punya const adalah: initialState Untuk mengatur ulang data di Store, saya melakukan yang berikut dengan setiap Reducer: contoh dengan appReducer.js :
akhirnya di router server:
sumber
Solusi berikut ini berfungsi untuk saya.
Pertama pada saat inisiasi aplikasi kita keadaan peredam baru dan baru dengan InitialState default .
Kami harus menambahkan tindakan yang menyerukan inital load APP untuk mempertahankan status default .
Saat keluar dari aplikasi, kita dapat dengan mudah menetapkan ulang status default dan peredam akan berfungsi sama seperti baru .
Wadah Aplikasi Utama
Reducer APP Utama
On Logout calling action untuk mengatur ulang status
Semoga ini bisa menyelesaikan masalah Anda!
sumber
Bagi saya untuk mengatur ulang negara ke keadaan awal, saya menulis kode berikut:
sumber
Satu hal yang tidak dilakukan solusi dalam jawaban yang diterima adalah menghapus cache untuk penyeleksi parameter. Jika Anda memiliki pemilih seperti ini:
Maka Anda harus melepaskannya saat logout seperti ini:
Kalau tidak, nilai memoized untuk panggilan terakhir pemilih dan nilai-nilai parameter terakhir akan tetap dalam memori.
Sampel kode berasal dari ngrx docs .
sumber
bagi saya yang paling berhasil adalah mengatur
initialState
alih - alihstate
:sumber
Pilihan lain adalah:
'@@redux/INIT'
adalah jenis tindakan yang dikirim redux secara otomatis saat AndacreateStore
, jadi dengan anggapan reduksi Anda sudah memiliki default, ini akan tertangkap oleh mereka dan memulai keadaan Anda dengan segar. Ini mungkin dianggap detail implementasi pribadi redux, jadi pembeli berhati-hatilah ...sumber
Cukup minta tautan keluar Anda menghapus sesi dan segarkan laman. Tidak diperlukan kode tambahan untuk toko Anda. Kapan pun Anda ingin mengatur ulang sepenuhnya keadaan, segarkan halaman adalah cara sederhana dan mudah diulang untuk menanganinya.
sumber
sumber
window.location.reload();
window
, mis. Asli-reaksi