Dominando o Hook useReducer no React: Guia Abrangente para Iniciantes
Tags: react, webdev, typescript
Published: 2023-08-23 02:14:23

O React é uma biblioteca JavaScript amplamente utilizada para construir interfaces de usuário interativas e reativas. Com o lançamento dos Hooks, o React introduziu uma maneira mais intuitiva e funcional de gerenciar estados e lógicas complexas em componentes funcionais. Um desses Hooks é o useReducer, que desempenha um papel vital no gerenciamento de estados complexos. Neste artigo, vamos mergulhar fundo no mundo do useReducer, entender suas nuances e aprender como aplicá-lo efetivamente em nossos projetos React.

**A. Descrição do useReducer Hook**
O useReducer é uma ferramenta poderosa que permite lidar com estados complexos em componentes funcionais do React. Ele segue o padrão de design conhecido como Reducer Pattern, uma abordagem popularizada pela arquitetura Flux. Esse Hook é particularmente útil quando você está trabalhando com estados que envolvem transições complexas e várias ações. A ideia central por trás do useReducer é dividir a lógica de atualização do estado em funções separadas, chamadas de redutores.

**B. Criação de um reducer usando useReducer**
Para criar um redutor usando o useReducer, você precisa definir um estado inicial e uma função redutora. O estado inicial é autoexplicativo - ele representa o estado inicial do componente. A função redutora é onde reside a lógica de atualização do estado com base nas ações. Veja como você pode fazer isso:

```

import React, { useReducer } from 'react';

const initialState = // estado inicial;

const reducer = (state, action) => {
  switch (action.type) {
    case 'AÇÃO_1':
      // lógica para ação 1
      return newState;
    case 'AÇÃO_2':
      // lógica para ação 2
      return newState;
    // mais cases para outras ações
    default:
      return state;
  }
};

const MyComponent = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  // resto do componente...
};
```

**C. Uso de dispatch para atualizar o estado**
A função dispatch é usada para enviar ações ao redutor, desencadeando atualizações no estado. Quando você chama dispatch, passa um objeto de ação que possui um tipo e, opcionalmente, outros dados relevantes. Aqui está um exemplo:

```
const MyComponent = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const handleClick = () => {
    dispatch({ type: 'AÇÃO_1', payload: 'dados adicionais' });
  };

  // resto do componente...
};
```

No exemplo acima, dispatch({ type: 'AÇÃO_1', payload: 'dados adicionais' }) envia uma ação de tipo 'AÇÃO_1' ao redutor, juntamente com os dados adicionais fornecidos no payload. O redutor, em seguida, processa essa ação e atualiza o estado, o que pode resultar em uma re-renderização do componente.

**D. Exemplos práticos de uso do useReducer**
Vamos explorar alguns cenários comuns em que o useReducer brilha:

1. Contador

```
const initialState = { count: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const handleIncrement = () => {
    dispatch({ type: 'INCREMENT' });
  };

  const handleDecrement = () => {
    dispatch({ type: 'DECREMENT' });
  };

  return (
    <div>
      <button onClick={handleIncrement}>Increment</button>
      <span>{state.count}</span>
      <button onClick={handleDecrement}>Decrement</button>
    </div>
  );
};
```

Nesse exemplo, o useReducer é empregado para criar um contador simples. As ações de 'INCREMENT' e 'DECREMENT' são despachadas ao redutor, que atualiza o estado com base nas ações, resultando em uma re-renderização do componente.

**2. Formulário de login**

```
const initialState = { username: '', password: '', loggedIn: false };

const reducer = (state, action) => {
  switch (action.type) {
    case 'UPDATE_USERNAME':
      return { ...state, username: action.payload };
    case 'UPDATE_PASSWORD':
      return { ...state, password: action.payload };
    case 'LOGIN':
      return { ...state, loggedIn: true };
    default:
      return state;
  }
};

const LoginForm = () => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const handleUsernameChange = (event) => {
    dispatch({ type: 'UPDATE_USERNAME', payload: event.target.value });
  };

  const handlePasswordChange = (event) => {
    dispatch({ type: 'UPDATE_PASSWORD', payload: event.target.value });
  };

  const handleLogin = () => {
    dispatch({ type: 'LOGIN' });
  };

  return (
    <form>
      <input
        type="text"
        value={state.username}
        onChange={handleUsernameChange}
        placeholder="Username"
      />
      <input
        type="password"
        value={state.password}
        onChange={handlePasswordChange}
        placeholder="Password"
      />
      <button onClick={handleLogin}>Login</button>
    </form>
  );
};
```

Aqui, o useReducer é utilizado para gerenciar um formulário de login. O estado é atualizado com base nas ações de 'UPDATE_USERNAME', 'UPDATE_PASSWORD' e 'LOGIN', resultando em um formulário interativo.

**Conclusão**
O useReducer é um instrumento valioso para lidar com estados complexos em componentes funcionais do React. Ele segue o padrão de design Reducer Pattern e oferece uma abordagem estruturada para gerenciar estados e ações. Ao dividir a lógica de atualização do estado em funções redutoras separadas, você pode criar componentes mais organizados e fáceis de manter. Agora que você tem um entendimento sólido do useReducer, sinta-se à vontade para explorar e aplicar esse Hook em seus próprios projetos React, aproveitando seus benefícios para criar interfaces interativas e robustas.