Skip to content
This page has been auto-translated and may contain errors.View in English

Hooks

Digamos que um componente precisa lembrar se um dropdown está aberto, ou precisa rodar algum código depois de renderizar para sincronizar com um servidor. Ambos são trabalhos para um hook. Você já usou dois deles: useState dá memória a um componente, e useEffect roda código depois de uma renderização para alcançar fora do React. Esses são os dois que você vai usar mais, e o resto dos built-ins seguem o mesmo padrão: você chama uma função dentro do seu componente, e ela te conecta a uma parte da máquina do React. O nome dessa função sempre começa com use, e esse prefixo é a definição completa de um hook.

Um tour pelos built-ins mais comuns

Você não precisa de todo hook no primeiro dia, mas é útil saber o que está disponível para reconhecer a ferramenta certa quando um problema exigir. Aqui estão os que aparecem mais frequentemente:

  • useRef mantém um valor mutável que sobrevive às renderizações sem causar uma. É também como você consegue uma referência direta a um elemento do DOM quando precisa, como focar um input.
  • useContext lê dados compartilhados de um provider ao redor, para que um componente profundamente aninhado consiga alcançar um valor sem você passar por todos os níveis do meio.
  • useReducer gerencia o estado através de uma função reducer, onde cada atualização descreve uma transição do estado atual para o próximo. É um bom ajuste quando mudanças de estado ficam complexas o suficiente para que um simples useState comece a apertar.
  • useMemo cacheia um valor computado entre renderizações e só o recalcula quando suas entradas mudam.
  • useCallback faz o mesmo para uma função, devolvendo a mesma instância de função entre renderizações em vez de uma nova a cada vez.

useMemo e useCallback ganham mais espaço em Memoization, uma vez que há uma história de desempenho real para contar. Refs e o DOM pega useRef na íntegra, e Context leva useContext deste resumo através de providers e estado compartilhado. Para useReducer, este capítulo é o tratamento mais profundo que ele recebe, então volte aqui quando precisar de um refresco. Por enquanto, o ponto é o padrão: um hook é sua forma de entrar em um recurso específico do React, e seu nome te diz que é um hook.

As regras dos hooks

Hooks vêm com duas regras, e o React conta com você seguindo-as.

Primeiro, chame hooks no nível superior do seu componente. Não os chame dentro de uma condição, um loop, ou uma função aninhada. Cada hook que um componente usa deve rodar em toda renderização, na mesma ordem, toda vez.

jsx
function Profile({ isLoggedIn }) {
  // Errado: este hook só roda às vezes
  if (isLoggedIn) {
    const [name, setName] = useState('')
  }

  // Correto: chame no nível superior, incondicionalmente
  const [name, setName] = useState('')
  // ...então use isLoggedIn dentro de sua lógica
}

Segundo, só chame hooks a partir de componentes de função React ou de outros hooks customizados. Funções JavaScript regulares não podem usar hooks, porque não há uma renderização de componente para React anexar o estado.

Escrevendo seus próprios hooks

Digamos que vários componentes precisam saber a largura da janela do navegador. Em vez de copiar a mesma lógica de useState e useEffect em cada um, você pode empacotar essa lógica uma vez:

jsx
import { useState, useEffect } from 'react'

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth)

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth)
    window.addEventListener('resize', handleResize)
    return () => window.removeEventListener('resize', handleResize)
  }, [])

  return width
}

Agora qualquer componente pode chamar const width = useWindowWidth() e obter um valor que se atualiza conforme a janela redimensiona. useWindowWidth é um hook customizado: uma função que chama outros hooks. Esse é o padrão completo, e porque é uma função, você pode dar a um pedaço de lógica com estado um nome, colocá-lo em um lugar, e reutilizá-lo entre componentes. O prefixo use é o que o marca como um hook, tanto para as ferramentas do React quanto para a próxima pessoa lendo seu código. Hooks customizados empacotam os hooks que você já tem em algo reutilizável; eles não adicionam novos poderes ao React.

Algumas regras práticas para explorar essa lista. Recorra a useRef quando você precisa manter um valor, como um ID de timer ou uma prop anterior, que não deve disparar uma re-renderização quando mudar, ou quando você precisa pegar um nó do DOM diretamente. Recorra a useContext quando um valor como o tema atual ou o usuário logado precisa alcançar vários níveis de componentes aninhados, e passá-lo por props em cada nível significaria tocar componentes que não se importam com isso de outra forma. Recorra a useReducer quando um único pedaço de estado tem vários sub-valores que se atualizam juntos, ou quando o próximo estado depende de uma ação específica em vez de um novo valor simples, já que um reducer mantém essa lógica de transição em uma função em vez de espalhada por vários setState calls. Recorra a useMemo ou useCallback só depois que você notou um real desempenho lento, na maioria das vezes um cálculo caro re-rodando em cada renderização, ou uma identidade de função que está quebrando memoização em outro lugar, como um filho React.memo'd ou o array de dependências de outro hook.

Nomear e extrair um hook customizado segue um padrão próprio. O nome sempre começa com use, para que as ferramentas do React e qualquer um lendo o código consiga dizer que é permitido chamar outros hooks. Quando você nota a mesma combinação de useState e useEffect, ou qualquer outro hook, aparecendo em mais de um componente, esse é o sinal para extrair: puxe a lógica para sua própria função com prefixo use e chame-a de cada componente em vez de repetir a lógica. Custom hooks in practice vai além, em o que um hook deve retornar e como desenhar suas opções.

As regras não são arbitrárias. React não conhece os nomes de suas variáveis de estado; ele rastreia os hooks em um componente pela ordem que são chamados. Primeiro hook, segundo hook, terceiro hook, e assim por diante. Na próxima renderização ele percorre a mesma lista na mesma ordem e combina cada chamada com o estado que configurou da última vez. Mantenha a ordem idêntica em toda renderização e a combinação se sustenta. Coloque um hook atrás de uma condição e a lista muda no momento em que essa condição inverte, para que React alinhe o estado errado com a chamada errada e o componente quebre de formas confusas. Chamar no nível superior, incondicionalmente, é o que garante uma ordem estável.

useMemo e useCallback merecem uma nota separada. Eles são otimizações manuais: você está dizendo ao React para manter um valor computado ou uma função para que ele não tenha que refazer o trabalho ou entregar uma nova instância em cada renderização. Eles custam um pouco de complexidade, e é tentador alcançá-los onde eles não realmente ajudam. O React Compiler cada vez mais torna-os desnecessários ao memoizar esse tipo de coisa para você no tempo de build, então trate alcançá-los à mão como algo que você faz deliberadamente, onde você mediu um custo real, em vez de um reflexo em cada valor.

JunoHooks deixam um componente usar recursos do React Um hook é uma função cujo nome começa com use, e ele conecta seu componente a um recurso do React como memória ou efeitos. Você já conheceu useState e useEffect, e os outros seguem o mesmo padrão.

A coisa principal a lembrar: chame hooks no topo do seu componente, nunca dentro de um if ou um loop, para que rodem do mesmo jeito a cada renderização.

JunoHooks deixam um componente usar recursos do React Além de useState e useEffect, você tem useRef para valores que sobrevivem renderizações sem disparar uma, useContext para pular prop drilling, useReducer para transições de estado estruturadas, e useMemo/useCallback para cachear.

Chame-os no nível superior de um componente ou outro hook, sempre na mesma ordem.

Quando você se vê repetindo lógica com estado, puxe-a para um hook customizado, uma função use que chama outros hooks, e reutilize-a.

JunoHooks deixam um componente usar recursos do React React combina hooks ao seu estado pela ordem de chamada em vez de pelo nome, então a ordem tem que ser idêntica em toda renderização. Esse fato único é de onde ambas as regras vêm.

Hooks customizados são composição: uma função chamando hooks, é por isso que as mesmas regras de ordem se aplicam dentro deles.

E trate useMemo/useCallback como otimizações deliberadas e medidas, já que o React Compiler está constantemente tornando as versões escritas à mão desnecessárias.

Próximo: Thinking in React, onde componentes, props, estado, e efeitos se juntam em um processo para transformar um design em uma UI.