Aanvullende Reducers in Redux
Laten we onze productenapplicatie openen,
en daarin het bestand productsSlice.js. Je hebt
waarschijnlijk gemerkt dat we de thunk fetchProducts
als een aparte functie hebben gemaakt? We hebben
dit gedaan omdat createSlice het definiëren
van thunks niet ondersteunt. Hoe kunnen we
in dit geval de reducer van de products slice
laten reageren op actions die buiten de
products slice zijn gedefinieerd?
We moeten immers de actions verwerken
die door de thunk fetchProducts worden verzonden.
Voor dergelijke gevallen heeft createSlice
de eigenschap extraReducers, die het mogelijk
maakt om aanvullende reducers toe te voegen, die
op hun beurt actions zullen verwerken die
niet in deze slice zijn gedefinieerd.
Laten we nu in de body van de functie createSlice
na de eigenschap reducers met alle reducers
nog een methode extraReducers toevoegen:
extraReducers() {},
We moeten aan deze methode een object
builder doorgeven, dat methodes heeft waarmee
je aanvullende reducers kunt toevoegen:
extraReducers(builder) {},
We zullen een van de methodes van builder gebruiken -
addCase, die als eerste parameter een action creator
accepteert en als tweede een reducer. Een van
de actions die fetchProducts zal verzenden
tijdens het verzoek is fetchProducts.pending,
wat ons vertelt dat het verzoek is verzonden.
Laten we in dit geval de status wijzigen in 'in progress'
(hiervoor was het 'idle'):
extraReducers(builder) {
builder.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
},
Laten we nu de action verwerken die wordt
verzonden bij een succesvol verzoek. Hier
zullen we niet alleen de status in de state
wijzigen in 'success', maar ook de producten
in de products slice halen uit de payload
van de action. Om alle producten te verzamelen
hebben we de methode concat nodig:
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 het geval van een mislukt verzoek zullen we de
status wijzigen in 'fail' en het foutbericht
in de state opslaan:
.addCase(fetchProducts.rejected, (state, action) => {
state.status = 'fail'
state.error = action.error.message
})
Als we nu onze applicatie starten
en in het menu op 'Products' klikken, dan
zien we na een paar seconden (herinner je de vertraging
die we op de server hebben ingesteld?) een
lijst met producten.
Op dezelfde manier zien we de wijzigingen in de Redux
DevTools. Nu verschijnen onze producten ook
in de state (bekijk het tabblad 'State'),
als je op de action
products/fetchProducts/fulfilled hebt geklikt.
Daar verschijnt ook de nieuwe status 'success'.
Klik nu op de action
products/fetchProducts/pending en bekijk
wat er nu anders is in het tabblad 'State'.
Het enige vervelende moment dat zich
voor kan doen (ik heb hierover gesproken
in de vorige les) is het dupliceren van
dataverzoeken. Hierdoor krijgen we
in de lijst niet 8, maar wel
16 producten en kritieke waarschuwingen
in de console van de ontwikkelaar. Laten we
dit in de volgende les oplossen.
Open je applicatie met studenten.
Open daarin het bestand studentsSlice.js. Voeg
in de body van de functie createSlice na de eigenschap
reducers de eigenschap extraReducers toe.
Geef aan de methode extraReducers een builder door.
Voeg met behulp van de methode builder.addCase
verwerking toe voor de actions pending,
fulfilled en rejected, die
worden verzonden door fetchStudents tijdens het
opvragen van gegevens, zoals getoond in de les.