useRef é um hook do React que cria um objeto ref mutável com uma propriedade .current, preservado entre renderizações do componente. Ao contrário do useState, alterar .current não provoca uma re-renderização, tornando useRef ideal para armazenar referências DOM, temporizadores e quaisquer valores que precisem persistir entre renderizações sem redesenhar a UI. De acordo com a Documentação do React (2025), o objeto ref é criado uma vez durante o tempo de vida do componente e não muda entre renderizações, garantindo estabilidade da referência.
Principais pontos
useRef é um hook adicionado no React 16.8 que retorna um objeto ref mutável com uma única propriedade .current. O valor inicial é atribuído a .current na montagem do componente. A principal diferença de uma variável comum é que o objeto ref sobrevive às re-renderizações: em renderizações subsequentes o React não recria o ref, mas retorna o mesmo objeto.
Internamente, useRef usa o mesmo mecanismo que useState e useEffect — uma lista ligada de hooks no nó fiber. No entanto, ao contrário do useState, o React não rastreia alterações no objeto ref, não enfileira atualizações nem agenda re-renderizações. Isto torna useRef um hook extremamente leve, sem impacto no desempenho mesmo sob alterações frequentes.
De acordo com a Equipa React — Hooks FAQ (2025), useRef é essencialmente uma “caixa” que armazena um valor. Açúcar sintático: const ref = useRef(valorInicial) equivale a const ref = { current: valorInicial } com a diferença de que o React garante que o objeto ref será o mesmo em cada renderização. Sem magia — apenas uma referência estável gerida pelo React.
import { useRef } from 'react';
function Component() {
const countRef = useRef(0);
// countRef.current = 0 inicialmente
// countRef.current = 5 após mutação
// Nenhuma re-renderização acontece!
}
O caso de uso mais comum do useRef é obter acesso direto a um elemento DOM. O React atribui a elementRef.current uma referência ao nó DOM após a montagem do componente. Isto é necessário para focar um input, medir dimensões de elementos, integrar com bibliotecas de animação e bibliotecas que não usam a renderização do React.
O React gere automaticamente as referências ref ao DOM: na montagem atribui o nó DOM real, na desmontagem anula (torna null). Isto garante que .current tenha sempre o valor atualizado e previne fugas de memória através de referências pendentes a elementos removidos. Não é necessária limpeza manual.
function AutoFocusInput() {
const inputRef = useRef(null);
useEffect(() => {
// Focar o input após montar o componente
inputRef.current?.focus();
}, []);
return <input ref={inputRef} type="text" />;
}
De acordo com a Documentação React — Refs e DOM (2025), não use ref para operações declarativas — abrir/fechar modais, gerir visibilidade. Para esses fins existem state e props. As refs destinam-se a operações imperativas que não podem ser expressas declarativamente: foco, seleção de texto, integração com bibliotecas de terceiros.
O segundo caso de uso mais importante é o armazenamento de valores arbitrários que precisam persistir entre renderizações mas cujas alterações não devem provocar uma re-renderização. Exemplos típicos: identificadores de temporizadores (setInterval/setTimeout), flags de cancelamento de pedidos, valores anteriores de props para comparação e quaisquer dados que não afetem a saída da UI.
Isto é especialmente útil no useEffect: useRef armazena o identificador do temporizador e o cleanup limpa-o. Se timerId fosse armazenado em useState, cada chamada a setTimerId provocaria uma re-renderização desnecessária que não é necessária nem para a lógica nem para a UI. useRef resolve este problema sem sobrecarga e sem re-renderizações desnecessárias.
function Timer() {
const intervalRef = useRef(null);
const start = () => {
intervalRef.current = setInterval(() => {
console.log('tique');
}, 1000);
};
const stop = () => {
clearInterval(intervalRef.current);
};
useEffect(() => stop, []);
return <><button onClick={start}>Start</button><button onClick={stop}>Stop</button></>;
}
O principal dilema — escolher entre useRef e useState — resolve-se com uma pergunta: “É necessária uma re-renderização quando o valor muda?”. Se sim — useState. Se não — useRef. useState armazena o estado que afeta a saída do componente; useRef armazena dados necessários para a lógica interna mas que não afetam a UI.
Na prática, os programadores usam frequentemente useRef para armazenar callbacks e evitar problemas com closures. Por exemplo, se useEffect subscreve um evento e o callback precisa do estado atual — armazene o callback em useRef. Em cada renderização, atualize ref.current com uma nova função, e o efeito invocará sempre o callback fresco sem necessidade de ressubscrever.
| Critério | useRef | useState |
|---|---|---|
| Re-renderização | Não provoca ao alterar | Provoca em cada setState |
| Mutação | Direta: ref.current = valor | Através de setter: setState(valor) |
| Uso em JSX | Não usado (sem efeito) | Usado na saída do componente |
| Exemplo | Temporizadores, referências DOM, valores anteriores | Dados de formulário, estado UI, flags |
Existe um anti-padrão: usar useRef para dados necessários em JSX cujas alterações não devem causar re-renderização. Isto leva à dessincronização — a UI mostra dados antigos enquanto ref.current já é novo. Se o valor é exibido na UI — use useState. Se usado apenas internamente — useRef.
A combinação useRef + useEffect é o padrão para rastrear valores anteriores de props. Armazene o valor anterior em ref, compare com o valor atual no useEffect e tome decisões com base na diferença. Isto é especialmente útil em animações quando precisa de saber qual era o valor antes da alteração.
function PriceDisplay({ price }) {
const prevPriceRef = useRef(price);
useEffect(() => {
const prevPrice = prevPriceRef.current;
if (price > prevPrice) {
animateUp();
} else if (price < prevPrice) {
animateDown();
}
prevPriceRef.current = price;
}, [price]);
return <span>${price}</span>;
}
De acordo com a Documentação React — Hooks FAQ (2025), este padrão é chamado de “padrão de valor anterior”. Funciona porque useRef preserva o valor entre renderizações, e useEffect executa-se após a confirmação das alterações. Primeiro o DOM é atualizado com o novo price, depois useEffect compara-o com o anterior (ainda em ref) e atualiza ref.current para o valor atual.
O erro mais frequente é ler ref.current durante a fase de renderização para calcular JSX. Como alterar ref.current não provoca re-renderização, o componente pode usar um valor desatualizado. Se .current participa na saída da UI — use useState. Se precisar de sincronizar ref e state, use useEffect para atualizar o state a partir do ref.
// ❌ Não leia ref.current durante a renderização para exibição
function BadComponent() {
const valRef = useRef(0);
return <p>{valRef.current}</p>; // NÃO será atualizado na mutação
}
// ✅ Use state para exibição, ref para lógica
function GoodComponent() {
const [val, setVal] = useState(0);
const valRef = useRef(0);
return <p>{val}</p>;
}
Outro erro comum é usar useRef como única forma de armazenar estado num componente quando os dados afetam realmente a UI. Os programadores escolhem useRef para evitar re-renderizações “desnecessárias”, mas acabam com uma UI que não atualiza. A abordagem correta: use useState para dados de UI e useRef apenas para valores auxiliares que não participam na renderização.
Perguntas frequentes
Sim, é um padrão comum — o padrão de estado anterior. Crie um ref e atualize-o no useEffect sempre que o valor rastreado mudar. Entre a renderização e o efeito, ref.current contém o valor anterior, que pode ser comparado com o atual. Isto não requer re-renderizações adicionais e funciona com qualquer tipo de dados.
O React atribui a ref.current o valor do nó DOM apenas depois de o elemento ser renderizado e adicionado ao DOM real. Durante a primeira renderização o componente ainda não está montado, por isso ref.current é igual ao valor inicial (null). O acesso ao DOM através de ref.current só é possível no useEffect ou em manipuladores de eventos chamados após a montagem.
createRef cria um novo objeto ref em cada renderização — só deve ser usado em componentes de classe. useRef cria o ref uma vez e retorna o mesmo objeto em todas as renderizações subsequentes. Em componentes funcionais use exclusivamente useRef; createRef causará perda de valor na re-renderização porque o objeto será recriado.
Sim, um objeto ref pode ser passado como uma prop normal: <Child inputRef={inputRef} />. O componente filho usa-o através de inputRef.current. No entanto, para passar um ref diretamente ao elemento DOM de um componente filho, use forwardRef — um HOC que permite reencaminhar refs através de props. Sem forwardRef, o ref não será automaticamente vinculado ao elemento DOM dentro do componente filho.
Vincule um ref ao elemento, depois no useEffect leia ref.current.getBoundingClientRect() ou ref.current.offsetWidth / offsetHeight. Para rastreamento reativo de mudanças de tamanho, use ResizeObserver dentro de useEffect: crie um observer, subscreva as alterações e atualize o state com as novas dimensões. Não se esqueça de desligar o observer no cleanup.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também