Redux no React - Assíncrono
Tags: javascript, webdev, beginners, redux
Published: 2022-01-06 17:42:36

## 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:

``` bash
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.

``` js
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.

``` js
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.

``` js
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.

``` js
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__.

``` js
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.

``` js
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._

``` js
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.