Entendendo useState e useReducer
Tags: react, typescript, ptbr
Published: 2021-02-01 22:08:27

# Introdução

O estado  em uma aplicação react é um faz parte dos conceitos fundamentais da biblioteca, desde a adoção dos hooks na versão 16.8 temos dois hooks que tem a função de lidar com estados, o useState e o useReducer. Nesse post eu vou tentar dar uma breve explicação sobre cada um dos hooks e suas particularidades;

# useState
De acordo com @types/react o hook useState possui a seguinte tipagem:

```typescript
function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
```
- O useState recebe um parâmetro, o initialState
  - Esse parâmetro pode ser um valor do tipo S ou uma função que retorna o tipo S, que é um `tipo genérico` ou seja, assume o tipo do seu estado, podendo ser um numero, string, ou um objeto qualquer.

- O useState retorna uma array de duas posições
  1. S se refere ao estado atual
  2. Dispatch<SetStateAction<S>> é a função que vai atualizar aquele componente, o dispatch pode receber o valor que o estado vai ser atualizado ou um callback do tipo `((prevState: S) => S);` recebendo o estado anterior e retornando o estado atual.

# useReducer
Ainda de acordo com @types/react o hook useReducer possui a seguinte tipagem,A estrutura básica do useReducer é uma função que recebe entre 2 e 3 parâmetros e retorna um array de duas posições:

```typescript
  function useReducer<R extends Reducer<any, any>, I>(                                  
            reducer: R,                                                                       
            initializerArg: I,                                                                
            initializer: (arg: I) => ReducerState<R>                                          
        ): [ReducerState<R>, Dispatch<ReducerAction<R>>]; 
)
```

- Os parâmetros do useReducer:
 
1. Reducer é um callback com a seguinte estrutura: `(prevState: S, action: A) => S;`, esse callback é o responsável por atualizar o estado, seria o equivalente ao SetStateAction do useState, porém com suas particularidades, a exemplo o parâmetro do callback, o action, nele é possível definir o tipo da ação, passar dados através do payload, o reducer deve ficar mais claro durante os exemplos. 

2. O initializerArg assim como initialState do useState é o parâmetro que vai receber o estado inicial do estado.

3. O `initializer`, esse recebe uma função responsável por modificar o initializeArg durante a montagem do componente modificando o estado inicial do reducer.

- O useReducer retorna um array com 2 parâmetros: `[ReducerState<R>, Dispatch<ReducerAction<R>>]`

1. O primeiro parâmetro é o State do useReducer
2. O segundo parâmetro é a função que vai chamar o reducer (1º parâmetro do useReducer), recebendo parâmetro action, onde no retorno do reducer o state é atualizado.

# Exemplos
partindo do caso de uso que o nosso estado é uma lista de jogadores, como podemos modificar essa lista utilizando o useState e o useReducer.

## useState

```jsx
/* No caso do useState se quisermos alterar esse estado em um componente abaixo podemos passar o setPlayer como prop. e montar o callback no componente abaixo, ou montar o addPlayer e passa-lo como prop. */

const [players, setPlayers] = useState(initialState); 
const addPlayer = (newPlayer) => {
  setPlayers([...players, newPlayer])
}
// Como o setPlayers vai ser chamado 👇
addPlayers('Ronaldo')

```


## useReducer
```jsx
/* Com o useReducer uma vez que defnimos a função reducer e suas ações passamos simplesmente o dispatch para baixo na arvore de componentes e cada componente chama a sua respectiva ação */

const reducer = (state, action) => {
    switch (action.type) {
      case "addPlayer": {
        const newState = [...state, action.payload];
        return newState;
      }
      default:
    }
  }
 const [players, dispatch] = useReducer(reducer, initialArg);
// Como o reducer vai ser chamado 👇
dispatch({ type : addPlayer, payload : "Ronaldo" })
```
Os dois códigos acima fazer a exatamente a mesma coisa, o useReducer parece muito mais verboso e compelxo que o useState, quais suas vantagens ? imagine uma situação que muitos outros métodos, adicionar, remover, atualizar... e ainda com outros estados como estado de loading, error entre outros. Como fariamos essas outras funções acessíveis para os componentes que a consomem ? criariamos uma nova prop para cada função, até setia possível mas imagina o caos que não seri esse componente, o useReducer aparece nesses casos onde você precisa lidar com muitos métodos e estados de um componente, a função reducer poderia ficar em um arquivo separado aumentando a qualidade e legibilidade do código, você saberia exatamente em qual tipo de action modificar, e ao invés de passar cada método com uma nova prop você pode passar só o dispatch e cada componente chama o tipo de ação que precisar.
 
> Quando você precisa lidar com apenas um estado, é mais simples conveniente utilizar o useState ao invés do use Reducer  apenas um estado para 

# References

- [React Documentation](https://reactjs.org/docs/hooks-reference.html#usereducer)