Reducer aggiuntivi in Redux
Apriamo la nostra applicazione di prodotti,
e in essa il file productsSlice.js. Probabilmente avete
notato che abbiamo creato il thunk fetchProducts
come una funzione separata? L'abbiamo fatto
perché createSlice non supporta la definizione
di thunks. Come possiamo quindi far sì che
il reducer dello slice products risponda alle action
che sono definite al di fuori di products?
Dopotutto, abbiamo proprio bisogno di gestire le action
che invia il thunk fetchProducts.
Per questi casi, createSlice ha
una proprietà extraReducers, che permette
di aggiungere reducer aggiuntivi, i quali
a loro volta gestiranno le action
definite non in questo slice.
Ora, nel corpo della funzione createSlice
dopo la proprietà reducers con tutti i reducer
aggiungiamo un altro metodo extraReducers:
extraReducers() {},
Dobbiamo passare a questo metodo un oggetto
builder, che ha dei metodi con
cui è possibile aggiungere
reducer aggiuntivi:
extraReducers(builder) {},
Useremo uno dei metodi di builder -
addCase, che accetta come primo parametro
un action creator, e come secondo un reducer. Una
delle action che ci invierà
fetchProducts durante la richiesta è
fetchProducts.pending, che ci indica
che la richiesta è stata inviata. In questo
caso cambiamo lo stato in 'in progress'
(prima era 'idle'):
extraReducers(builder) {
builder.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
},
Ora gestiamo l'action che viene inviata
in caso di richiesta riuscita. Qui
cambieremo non solo lo stato nello store in
'success', ma prenderemo i prodotti
nello slice products dal payload dell'action.
Per raccogliere tutti i prodotti avremo bisogno
del metodo 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)
})
},
In caso di richiesta fallita, cambieremo
lo stato in 'fail' e salveremo nello store
il messaggio di errore:
.addCase(fetchProducts.rejected, (state, action) => {
state.status = 'fail'
state.error = action.error.message
})
Se avviamo ora la nostra applicazione
e clicchiamo su 'Products' nel menu,
dopo un paio di secondi (ricordate il ritardo
che abbiamo impostato sul server?) vedremo
una lista di prodotti.
Allo stesso modo vedremo i cambiamenti anche in Redux
DevTools. Ora i nostri prodotti appariranno
nello store (guardate la scheda 'State'),
se avete cliccato sull'action
products/fetchProducts/fulfilled.
Lì apparirà anche il nuovo stato 'success'.
Cliccate ora sull'action
products/fetchProducts/pending e guardate
cosa è cambiato nella scheda 'State'.
L'unico spiacevole inconveniente che
potrebbe capitarvi (ne ho parlato nella
lezione precedente) è la duplicazione
della richiesta dei dati. Di conseguenza, nella
nostra lista non avremo 8, ma ben
16 prodotti e avvisi critici
nella console dello sviluppatore.
Affrontiamo questo problema nella prossima lezione.
Aprite la vostra applicazione con gli studenti.
Aprite in essa il file studentsSlice.js. Nel
corpo della funzione createSlice dopo la proprietà
reducers aggiungete la proprietà extraReducers.
Passate al metodo extraReducers il builder.
Utilizzando il metodo builder.addCase
aggiungete la gestione per le action pending,
fulfilled e rejected, che
vengono inviate da fetchStudents durante la richiesta
dei dati, come mostrato nella lezione.