Redutores Adicionais no Redux
Vamos abrir nossa aplicação de produtos,
e nela o arquivo productsSlice.js. Você provavelmente
percebeu que criamos a thunk fetchProducts
como uma função separada? Fizemos isso
porque createSlice não suporta a definição
de thunks. Então, como podemos fazer com que
o redutor do slice products responda a ações
que são definidas fora do products?
Afinal, precisamos processar as ações
que a thunk fetchProducts envia.
Para tais casos, o createSlice tem
a propriedade extraReducers, que permite
adicionar redutores adicionais, que
por sua vez processarão as ações
definidas não neste slice.
Agora, no corpo da função createSlice
após a propriedade reducers com todos os redutores
vamos adicionar mais um método extraReducers:
extraReducers() {},
Devemos passar a este método um objeto
builder, que tem métodos, com
os quais podemos adicionar
redutores adicionais:
extraReducers(builder) {},
Vamos usar um dos métodos do builder -
addCase, que aceita como primeiro parâmetro
um criador de ação (action creator), e como segundo, um redutor. Uma das
ações que o fetchProducts enviará
durante a solicitação é
fetchProducts.pending, que nos diz
que a solicitação foi enviada. Vamos neste
caso alterar o status para 'in progress'
(antes era 'idle'):
extraReducers(builder) {
builder.addCase(fetchProducts.pending, (state) => {
state.status = 'in progress'
})
},
Agora vamos processar a ação que será enviada
em caso de sucesso da solicitação. Aqui vamos
alterar não apenas o status no state para
'success', mas também obter os produtos no
slice products a partir do payload da ação.
Para coletar todos os produtos, precisaremos
do método 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)
})
},
Em caso de falha na solicitação, vamos alterar
o status para 'fail' e registrar no state
a mensagem de erro:
.addCase(fetchProducts.rejected, (state, action) => {
state.status = 'fail'
state.error = action.error.message
})
Se executarmos nossa aplicação agora
e clicarmos em 'Products' no menu,
após alguns segundos (lembra do atraso
que definimos no servidor?) veremos
a lista de produtos.
Da mesma forma, veremos as mudanças no Redux
DevTools. Agora nossos produtos aparecerão
no state (verifique a aba 'State'),
se você clicou na ação
products/fetchProducts/fulfilled.
Lá também aparecerá o novo status 'success'.
Agora clique na ação
products/fetchProducts/pending e veja
como a aba 'State' difere agora.
O único momento desagradável que
pode acontecer com você (falei sobre isso
na lição anterior) - é a duplicação
da solicitação de dados. Como resultado, em
nossa lista teremos não 8, mas incríveis
16 produtos e avisos críticos
no console do desenvolvedor. Vamos
resolver isso na próxima lição.
Abra sua aplicação de estudantes.
Abra nela o arquivo studentsSlice.js. No
corpo da função createSlice após a propriedade
reducers adicione a propriedade extraReducers.
Passe ao método extraReducers o builder.
Usando o método builder.addCase
adicione o tratamento para as ações pending,
fulfilled e rejected, que
são enviadas pelo fetchStudents durante a solicitação
de dados, como mostrado na lição.