useRef — o que é, o hook de referências e trabalho com o DOM no React

Autor: IT Sectr Publicado: 2026-07-04 Tempo de leitura: 9 min

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 — hook para criar um objeto ref mutável com a propriedade .current.
  • Sem re-renderização — alterar .current não provoca uma nova renderização do componente.
  • Referências DOM — passado na prop ref do elemento para acesso direto ao nó DOM.
  • Armazenamento de valores — ideal para temporizadores, valores anteriores e quaisquer dados entre renderizações.
  • Referência estável — o objeto ref não muda entre renderizações, ao contrário dos closures.

O que é useRef no React

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.

jsx
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!
}

Acesso a elementos DOM com useRef

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.

jsx
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.

Armazenamento de valores mutáveis sem re-renderizações

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.

jsx
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></>;
}

useRef vs useState: quando usar cada um

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ériouseRefuseState
Re-renderizaçãoNão provoca ao alterarProvoca em cada setState
MutaçãoDireta: ref.current = valorAtravés de setter: setState(valor)
Uso em JSXNão usado (sem efeito)Usado na saída do componente
ExemploTemporizadores, referências DOM, valores anterioresDados 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.

useRef em combinação com useEffect

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.

jsx
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.

Erros comuns com useRef

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.

  • Ref em JSX — ler ref.current dentro de uma função de renderização leva à dessincronização entre UI e dados.
  • Ref como dependência de useEffect — ref.current não deve estar no array de dependências; o React não rastreia as suas alterações.
  • Verificação de null esquecida — na desmontagem ref.current torna-se null; verifique antes de aceder.
  • Armazenar funções em ref — atualize ref.current em cada renderização se usar o padrão de callback fresco.
jsx
// ❌ 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

Pode usar-se useRef para armazenar o estado anterior?

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.

Porque é que ref.current é null na primeira renderização?

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.

Qual é a diferença entre useRef e createRef?

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.

Pode passar-se useRef através de props?

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.

Como medir o tamanho de um elemento com useRef?

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

  • useRef — hook para criar um objeto ref mutável preservado entre renderizações sem provocar re-renderização.
  • Acesso ao DOM — a prop ref é passada a um elemento para acesso direto ao nó DOM; disponível após montagem.
  • Armazenamento de dados — temporizadores, callbacks, flags e quaisquer valores que não afetem a UI armazenam-se em ref.
  • useRef vs useState — escolha useState se a alteração deve re-renderizar a UI; useRef se não.
  • Padrão de valor anterior — armazene o valor anterior em ref, atualize no useEffect para comparação.
  • Ref em JSX — não leia ref.current na fase de renderização; isto leva à dessincronização entre UI e dados.
  • forwardRef — use para passar um ref através de props a um componente filho.

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.

Discutir o projeto

Leia também