DevPath · Aprenda a programar ESPTEN

useReducer e Context

useReducer: estado com transições claras

Quando usar useReducer em vez de useState?

useState é perfeito para valores simples e independentes. Mas quando o estado é complexo (vários campos relacionados) ou as atualizações seguem transições claras (várias formas distintas de alterá-lo), espalhar a lógica por muitos setX se torna frágil e difícil de acompanhar.

useReducer concentra toda essa lógica em uma única função: o reducer.

O reducer: (state, action) => nextState

Um reducer é uma função pura que recebe o estado atual e uma ação, e retorna o próximo estado. Ele não muta o estado: constrói e retorna um novo.

function reducer(state, action) {
  switch (action.type) {
    case "incrementar":
      return { contagem: state.contagem + 1 };
    case "decrementar":
      return { contagem: state.contagem - 1 };
    default:
      return state;
  }
}

dispatch: enviar ações

No componente, useReducer(reducer, estadoInicial) retorna um par: o estado atual e uma função chamada dispatch. Para alterar o estado, você "despacha" uma ação descrevendo o que aconteceu:

function Contador() {
  const [state, dispatch] = useReducer(reducer, { contagem: 0 });

  return (
    <div>
      <p>Contagem: {state.contagem}</p>
      <button onClick={() => dispatch({ type: "incrementar" })}>+1</button>
      <button onClick={() => dispatch({ type: "decrementar" })}>-1</button>
    </div>
  );
}

A ação costuma ser um objeto com uma propriedade type (e, se necessário, dados extras como payload). A vantagem: a lógica vive em um único lugar, é fácil de ler e de testar, e os componentes apenas dizem o que aconteceu, não como o estado muda.

Nos exercícios, useReducer já está disponível: use-o diretamente, sem importá-lo.

Coloque isto em prática

O DevPath é um curso prático: aqui você lê a teoria; no app você a coloca em prática com exercícios que rodam de verdade, offline.

Comece grátis no app →
Context API: evitar o prop drilling →