DevPath · Aprenda a programar ESPTEN

Hooks personalizados e desempenho

Hooks personalizados: lógica com estado reutilizável

O problema: lógica repetida

Imagine dois componentes que precisam de um interruptor (ligado/desligado). Em ambos você escreveria a mesma coisa:

const [aberto, setAberto] = useState(false);
const alternar = () => setAberto((v) => !v);

Copiar e colar essa lógica funciona, mas ela se desincroniza com o tempo. A solução do React são os hooks personalizados.

O que é um hook personalizado

Um hook personalizado é, simplesmente, uma função cujo nome começa com use e que usa outros hooks por dentro. Encapsula lógica com estado e retorna o que o componente precisa:

function useToggle(inicial = false) {
  const [valor, setValor] = useState(inicial);
  const alternar = () => setValor((v) => !v);
  return [valor, alternar];
}

Agora qualquer componente reutiliza essa lógica sem duplicá-la:

function Painel() {
  const [aberto, alternar] = useToggle(false);
  return (
    <div>
      <button onClick={alternar}>Mostrar/ocultar</button>
      {aberto && <p>Conteúdo visível</p>}
    </div>
  );
}

O importante: cada componente que chama useToggle obtém seu próprio estado, isolado. Você compartilha a lógica, não o estado.

Outro exemplo: useContador

Um hook pode compor vários hooks e expor a API que for mais conveniente (um objeto, um array, funções...):

function useContador(inicial = 0) {
  const [cuenta, setCuenta] = useState(inicial);
  const incrementar = () => setCuenta((c) => c + 1);
  const reiniciar = () => setCuenta(inicial);
  return { cuenta, incrementar, reiniciar };
}

As regras dos hooks

Para que o React possa associar cada chamada ao seu estado, os hooks têm duas regras inquebráveis:

  1. Chame-os somente no nível superior. Nunca dentro de if, laços, condicionais ou funções aninhadas. A ordem das chamadas deve ser a mesma em cada render.
  2. Chame-os somente a partir de componentes React ou de outros hooks personalizados. Não a partir de funções JavaScript normais.
// ❌ ERRADO: hook dentro de um if (a ordem muda entre renders)
if (ativo) {
  const [x, setX] = useState(0);
}

// ✅ CERTO: no nível superior; a condição vai por dentro
const [x, setX] = useState(0);
if (ativo) { /* usa x */ }

Um hook personalizado é apenas uma convenção de nome (use...) mais estas regras. Não há "mágica": é uma função que organiza seus hooks.

Exemplos

Um hook useToggle reutilizável

function useToggle(inicial) {
  const [valor, setValor] = React.useState(inicial);
  const alternar = () => setValor((v) => !v);
  return [valor, alternar];
}
// Simulação: duas "instâncias" têm estado independente
let estado1 = false, estado2 = true;
console.log("início:", estado1, estado2);
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 →
Desempenho: por que o React re-renderiza →