Escolher entre cálculo, evento e sincronização
Nem todo o trabalho pertence a um Effect. Um nome completo derivado de dois campos pode ser calculado durante o render. Um envio que corresponde ao clique de confirmação pertence à lógica dessa interação.
Uma subscrição que deve existir enquanto o componente está ligado a um sistema externo é uma necessidade de sincronização. O exemplo acompanha a largura do viewport, que pode mudar independentemente dos eventos do formulário. Essa é a razão para o listener externo.
Antes de adicionar um Effect, descreve qual sistema está a ser sincronizado e qual condição deve fazer começar, atualizar ou terminar essa relação. Se só estás a copiar um valor derivável para outro estado, revê primeiro o modelo de dados.
Setup e cleanup como um par
O setup cria a relação externa e pode devolver uma função de cleanup. Quando mudam dependências após um commit, React executa o cleanup com os valores anteriores antes de estabelecer o novo setup. Ao remover a instância, executa também o cleanup correspondente.
No exemplo, measure é criado dentro do setup e a função devolvida remove esse mesmo listener. Registar um handler vazio adicional ou limpar apenas uma variável não liberta a subscrição anterior. Em ligações externas, o mesmo princípio exige fechar a ligação criada por aquele setup.
A unidade de análise é o recurso concreto, não apenas o nome da função que aparece no código.
Dependências que descrevem a lógica
A lista deve incluir os valores reativos usados pela lógica, como props e estado. React compara cada dependência com a anterior através de Object.is; não faz uma comparação profunda arbitrária de objetos. Omitir o segundo argumento pede nova execução após cada commit. [] declara que não há dependências reativas nessa lógica, não que ela deve ler valores novos sem voltar a executar.
No exemplo, o Effect usa window e um setter de identidade estável, sem ler width ou props. Se uma ligação passasse a depender de roomId, essa prop teria de participar na lista. Silenciar um aviso para conservar [] pode esconder uma ligação à sala antiga enquanto a interface já apresenta outra.
Objetos novos e religações evitáveis
Um objeto options criado no corpo do componente é novo em cada render, mesmo quando contém as mesmas strings. Se o Effect depende desse objeto, escrever noutro campo pode desencadear cleanup e nova ligação. Uma solução simples é construir options dentro do Effect e depender dos valores reativos que o compõem.
Se serverUrl for uma constante de módulo e roomId uma prop, a lista pode ser [roomId]. Se serverUrl passar a ser prop, também precisa de entrar na análise. A correção não é apagar indiscriminadamente dependências; é fazer a estrutura corresponder à configuração que realmente governa a ligação.
Refs para valores que não agendam render
useRef devolve um objeto estável para a instância, com uma propriedade current mutável. Mudar current não informa React de que deve renderizar. Por isso width é estado no exemplo, enquanto inputRef guarda a referência ao nó para uma ação imperativa.
Depois de o input ser criado, React associa o nó a current; ao removê-lo, current pode voltar a null. O handler de foco considera essa possibilidade. Não uses uma ref como substituição automática do estado visual nem leias e escrevas current durante o render para contornar pureza, exceto nos padrões de inicialização permitidos.
A escolha depende de se a mudança deve determinar a apresentação ou apenas conservar uma referência para uso posterior.
Desenvolvimento, remount e paint
Em Strict Mode, React pode exercitar um ciclo adicional de setup e cleanup em desenvolvimento para revelar problemas de simetria. Uma flag didRun pode reduzir mensagens no log sem fechar a ligação ao sair. Quando a página volta a montar, recursos antigos podem continuar ativos.
O objetivo é que setup, cleanup e novo setup deixem a relação correta. Também evita afirmar que useEffect corre sempre depois do paint: a documentação distingue Effects associados a interações e outros casos. Effects só correm no cliente, não na renderização do servidor.
O exemplo começa com uma apresentação sem medição e só consulta window dentro do Effect no cliente.
Diagnosticar recursos e observações
Perante callbacks duplicados, identifica quantas subscrições estão ativas e que cleanup deveria remover cada uma. Perante uma ligação antiga, compara as props lidas com a lista de dependências. Perante religações a cada tecla, procura objetos ou funções criados no render que mudam de identidade.
Estes são diagnósticos diferentes e não pedem todos uma ref ou []. Regista o estado antes e depois de montar, alterar configuração e sair. Os casos são modelos de decisão por leitura; não afirmam que um ensaio de browser tenha sido executado.
Pedidos assíncronos, resultados fora de ordem e Suspense terão limites próprios na aula seguinte.
import {useEffect, useRef, useState} from 'react';
export default function ViewportNote() {
const [width, setWidth] = useState(null);
const inputRef = useRef(null);
useEffect(() => {
function measure() { setWidth(window.innerWidth); }
measure();
window.addEventListener('resize', measure);
return () => window.removeEventListener('resize', measure);
}, []);
function focusNote() { inputRef.current?.focus(); }
return <section>
<p>Viewport: {width === null ? 'Waiting for client measurement' : width}</p>
<label>Local note <input ref={inputRef} name="note" /></label>
<button type="button" onClick={focusNote}>Focus note</button>
</section>;
}O setup mede a largura no cliente e regista um listener. O cleanup remove exatamente esse listener. width é estado porque a apresentação deve reagir à medição; inputRef permite focar o nó montado num clique. [] é adequado aqui porque a lógica não lê props ou outro estado reativo.
Armadilhas comuns
Usar [] para esconder props usadas; depender de um objeto novo em cada render; usar uma flag para evitar setup sem cleanup; alterar uma ref e esperar render; garantir que todo o Effect corre depois do paint.
Tópicos relacionados: Eventos, snapshots de estado e filas de atualização · Reducers, contexto e estado partilhado · Dados assíncronos, Suspense e limites de erro
Effects sincronizam a interface com sistemas externos e precisam de dependências e cleanup coerentes. Refs retêm valores mutáveis sem agendar render. Usa estado para dados que devem determinar a apresentação.
Referência: Effect lifecycle and dependencies · React 19.3.0; JSX