Reduceri suplimentari în Redux
Să deschidem aplicația noastră cu produse,
iar în ea fișierul productsSlice.js. Probabil că
ați observat că am creat thunk-ul fetchProducts
ca o funcție separată? Am făcut asta pentru că
createSlice nu suportă definirea
thunks. Cum putem în acest caz să facem
reducer-ul slice-ului products să răspundă la acțiunile
care sunt definite în afara products?
La urma urmei, tocmai trebuie să procesăm acțiunile
pe care le trimite thunk-ul fetchProducts.
Pentru astfel de cazuri, createSlice are
proprietatea extraReducers, care permite
adăugarea de reduceri suplimentari, care
la rândul lor vor procesa acțiunile,
definite nu în acest slice.
Acum să în corpul funcției createSlice
după proprietatea reducers cu toți reducerii
adaugăm încă o metodă extraReducers:
extraReducers() {},
Acestei metode trebuie să-i transmitem un obiect
builder, care are metode, cu
ajutorul cărora se pot adăuga
reduceri suplimentari:
extraReducers(builder) {},
Vom folosi una dintre metodele builder -
addCase, care primeste ca prim parametru
un action creator, iar ca al doilea un reducer. Una dintre
acțiunile, pe care o va trimite
fetchProducts la cerere este
fetchProducts.pending, ceea ce ne spune
că cererea a fost trimisă. Să în acest
caz să schimbăm statusul în 'in progress'
(până acum era 'idle'):
extraReducers(builder) {
builder.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
},
Acum să procesăm acțiunea care se va trimite
în cazul unei cereri de succes. Aici vom
schimba nu doar statusul în starea pe
'success', ci și vom lua produsele în
slice-ul products din payload al acțiunii.
Pentru a aduna toate produsele vom avea nevoie de
metoda concat:
extraReducers(builder) {
builder
.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
.addCase(fetchProducts.fulfilled, (state, action) => {
state.status = 'success'
state.products = state.products.concat(action.payload)
})
},
În cazul unei cereri nereușite vom schimba
statusul în 'fail' și vom scrie în starea
mesajul de eroare:
.addCase(fetchProducts.rejected, (state, action) => {
state.status = 'fail'
state.error = action.error.message
})
Dacă acum pornim aplicația noastră
și în meniu facem clic pe 'Products', atunci
peste câteva secunde (vă amintiți de întârzierea,
pe care am setat-o pe server?) vom vedea
lista cu produse.
Tot așa vom vedea schimbări și în Redux
DevTools. Acum produsele noastre vor apărea și
în starea (uitați-vă la fila 'State'),
dacă ați făcut clic pe acțiunea
products/fetchProducts/fulfilled.
Acolo va apărea și noul status 'success'.
Faceți clic acum pe acțiunea
products/fetchProducts/pending și uitați-vă,
cu ce diferă acum fila 'State'.
Singurul moment neplăcut, care
vă poate să vi se întâmple (am vorbit despre asta
în lecția precedentă) - este duplicarea
cererii de date. În rezultat, la noi
în lista se va obține nu 8, ci întregi
16 produse și avertismente critice
în consola dezvoltatorului. Să
ne ocupăm de asta în lecția următoare.
Deschideți aplicația voastră cu studenții.
Deschideți în ea fișierul studentsSlice.js. În
corpul funcției createSlice după proprietatea
reducers adăugați proprietatea extraReducers.
Transmiteți metodei extraReducers builder.
Cu ajutorul metodei builder.addCase
adăugați procesarea pentru acțiunile pending,
fulfilled și rejected, care
sunt trimise de fetchStudents la cererea
datelor, așa cum este arătat în lecție.