Redux Thunk
O que é?
É um pacote complementar do Redux que permite a execução de código assíncrono, para o armazenamento e manipulação de estados. Esse pacote é necessário, pois normalmente o Redux aceita apenas código 100% síncrono.
Instalando
Por se tratar de um pacote complementar, ele não vem instalado junto ao Redux, porém para instalá-lo é muito simples, basta utilizar o comando:
npm i redux-thunk
Não sendo necessário nenhuma configuração adicional.
Aplicando Redux-Thunk no Redux
Para termos acesso às funcionalidades assíncronas, precisamos passar um segundo parâmetro para a função createStore()
, que é outra função chamada applyMiddleware()
, que por sua vez recebe o thunk do Redux-Thunk como parâmetro.
const store = createStore(rootReducer, applyMiddleware(thunk));
Redux-Thunk Actions
Sintaxe
A sintaxe de uma Action Creator assíncrona, possibilitada pelo Redux-Thunk, consiste em uma função que retorna outra função, essa que recebe o dispatch como parâmetro padrão.
function asyncAction() {
return (dispatch) => {};
}
Em geral a sintaxe é a do exemplo acima, porém podemos “incrementar” a Action Creator o quanto quisermos, desde que ela retorne ao final um objeto no formato esperado pelo Reducer.
function fetchData() {
return (dispatch) => {
dispatch(startRequest());
return fetch(<API endpoint>)
.then((res) => res.json()
.then(
(data) => dispatch(getData(data)),
(error) => dispatch(getError(error)),
));
};
}
No exemplo acima temos uma função que pode disparar três Actions, sendo elas respectivamente startRequest()
, getData()
e getError()
. O nome dado no exemplo é genérico, porém em funções de requisição à API não é incomum que tenhamos exatamente essas três Actions, porém com nomes mais apropriados.
startRequest
A startRequest()
é uma Action que tem como função alterar o estado de “loading” da aplicação, assim podemos realizar renderizações condicionais como fazíamos sem usar o Redux.
const startRequest = () => ({ type: START_REQUEST });
getData
A getData()
, como o nome dá a entender, é uma Action que irá salvar em nosso estado os dados recebidos da API, sendo necessário preparar o Reducer para os diferentes tipos de dados.
const getData = (payload) => ({ type: GET_DATA, payload });
getError
E por fim a getError()
é uma Action que irá armazenar o erro de requisição em nosso estado, isso se houver um erro.
const getError = (payload) => ({ type: GET_ERROR, payload });
Exemplo de Reducer
Abaixo será mostrado um Reducer genérico de acordo com a função e as actions exemplificadas acima.
Já adiantando que a estrutura base continuará sendo a mesma.
const INITIAL_STATE = {
data: [],
error: undefined,
loading: false,
}
export default function myReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case START_REQUEST:
return {
...state,
loading: true,
}
case GET_DATA:
return {
...state,
data: action.payload,
loading: false,
}
case GET_ERROR:
return {
...state,
error: action.payload,
loading: false,
}
default:
return state;
}
}
No Reducer acima temos três casos, o primeiro apenas altera a chave loading
, indicando que uma requisição foi iniciada, já o segundo e terceiro caso, além de alterarem novamente a chave loading
, para indicar que a requisição foi concluída, também armazenam a resposta dessa requisição, seja ela dados ou erros (respectivamente).
E o resto?
O resto da estrutura base do Redux (reducers, store, Provider e actions síncronas) continuem funcionando exatamente como antes.
Top comments (0)