useRef é um Hook React que permite que você referencie um valor que não é necessário para renderização.

const ref = useRef(initialValue)

Referência

useRef(initialValue)

Chame useRef no topo do seu componente para declarar uma ref.

import { useRef } from 'react';

function MyComponent() {
const intervalRef = useRef(0);
const inputRef = useRef(null);
// ...

Veja mais exemplos abaixo.

Parâmetros

  • initialValue: O valor que você quer que a propriedade current do objeto ref tenha inicialmente. Pode ser um valor de qualquer tipo. Este argumento é ignorado após a renderização inicial.

Retorna

useRef retorna um objeto com uma única propriedade:

  • current: Inicialmente, é definido para o initialValue que você passou. Você pode, mais tarde, definir para outra coisa. Se você passar o objeto ref para o React como um atributo ref para um nó JSX, o React definirá sua propriedade current.

Nas próximas renderizações, useRef retornará o mesmo objeto.

Ressalvas

  • Você pode mutar a propriedade ref.current. Diferente do state, é mutável. No entanto, se ele contiver um objeto que é usado para renderização (por exemplo, uma parte do seu state), então você não deve mutar esse objeto.
  • Quando você muda a propriedade ref.current, o React não re-renderiza o seu componente. O React não está ciente quando você o muda porque uma ref é um objeto JavaScript simples.
  • Não escreva ou leia ref.current durante a renderização, exceto para inicialização. Isso torna o comportamento do seu componente imprevisível.
  • No Strict Mode, o React irá chamar a função do seu componente duas vezes para ajudar você a encontrar impurezas acidentais. Esse é um comportamento apenas para desenvolvimento e não afeta a produção. Cada objeto ref será criado duas vezes, mas uma das versões será descartada. Se a função do seu componente é pura (como deveria ser), isso não deve afetar o comportamento.

Uso

Referenciando um valor com uma ref

Chame useRef no nível mais alto do seu componente para declarar um ou mais refs.

import { useRef } from 'react';

function Stopwatch() {
const intervalRef = useRef(0);
// ...

useRef retorna um objeto ref com uma única propriedade current inicialmente definida para o valor inicial que você forneceu.

Nas renderizações seguintes, useRef retornará o mesmo objeto. Você pode mudar sua propriedade current para armazenar informações e lê-las depois. Isso pode fazer você lembrar do state, mas há uma diferença importante.

Mudar uma ref não dispara uma re-renderização. Isso significa que as refs são perfeitas para armazenar informações que não afetam a saída visual do seu componente. Por exemplo, se você precisar armazenar um ID de intervalo e recuperá-lo depois, você pode colocá-lo em uma ref. Para atualizar o valor dentro da ref, você precisa mudar manualmente sua propriedade current:

function handleStartClick() {
const intervalId = setInterval(() => {
// ...
}, 1000);
intervalRef.current = intervalId;
}

Mais tarde, você pode ler o ID do intervalo da ref para que possa chamar clear o intervalo:

function handleStopClick() {
const intervalId = intervalRef.current;
clearInterval(intervalId);
}

Ao usar uma ref, você garante que:

  • Você pode armazenar informações entre as re-renderizações (diferente das variáveis normais, que reiniciam em cada renderização).
  • Mudá-la não dispara uma re-renderização (diferente das variáveis do state, que disparam uma re-renderização).
  • A informação é local para cada cópia do seu componente (diferente das variáveis externas, que são compartilhadas).

Mudar uma ref não dispara uma re-renderização, então refs não são apropriadas para armazenar informações que você quer exibir na tela. Use state para isso. Leia mais sobre escolher entre useRef e useState.

Exemplos de referência de um valor com useRef

Example 1 of 2:
Contador de cliques

Este componente usa uma ref para controlar quantas vezes o botão foi clicado. Note que é aceitável usar uma ref em vez de state aqui porque a contagem de cliques é somente lida e escrita em um manipulador de evento.

import { useRef } from 'react';

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('You clicked ' + ref.current + ' times!');
  }

  return (
    <button onClick={handleClick}>
      Click me!
    </button>
  );
}

Se você mostrar {ref.current} no JSX, o número não irá atualizar no clique. Isso ocorre porque definir ref.current não dispara uma re-renderização. Informações que são usadas para renderização deveriam ser state, em vez disso.

Pitfall

Não escreva ou leia ref.current durante a renderização.

O React espera que o corpo do seu componente se comporte como uma função pura:

  • Se os inputs (props, state, e contexto) forem os mesmos, ele deverá retornar exatamente o mesmo JSX.
  • Chamá-la em uma ordem diferente ou com argumentos diferentes não deverá afetar os resultados de outras chamadas.

Ler ou escrever uma ref durante a renderização quebra essas expectativas.

function MyComponent() {
// ...
// 🚩 Não escreva uma ref durante a renderização
myRef.current = 123;
// ...
// 🚩 Não leia uma ref durante a renderização
return <h1>{myOtherRef.current}</h1>;
}

Você pode ler ou escrever refs de manipuladores de eventos ou effects, em vez disso.

function MyComponent() {
// ...
useEffect(() => {
// ✅ Você pode ler ou escrever refs em effects
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ Você pode ler ou escrever refs em manipuladores de eventos
doSomething(myOtherRef.current);
}
// ...
}

Se você tiver que ler ou escrever algo durante a renderização, use o state em vez disso.

Quando você quebra essas regras, seu componente ainda pode funcionar, mas a maioria dos recursos mais novos que estamos adicionando ao React dependerão dessas expectativas. Leia mais sobre manter seus componentes puros.


Manipulando o DOM com uma ref

É particularmente comum usar uma ref para manipular o DOM. O React tem suporte embutido para isso.

Primeiramente, declare um objeto ref com um valor inicial de null:

import { useRef } from 'react';

function MyComponent() {
const inputRef = useRef(null);
// ...

Então passe o seu objeto ref como o atributo ref para o JSX do nó do DOM que você quer manipular:

// ...
return <input ref={inputRef} />;

Depois que o React cria o nó do DOM e o coloca na tela, o React irá definir a propriedade current do seu objeto ref para esse nó do DOM. Agora você pode acessar o nó DOM do <input> e chamar métodos como focus():

function handleClick() {
inputRef.current.focus();
}

O React irá definir a propriedade current de volta para null quando o nó for removido da tela.

Leia mais sobre manipular o DOM com refs.

Exemplos de manipulação do DOM com useRef

Example 1 of 4:
Focando uma entrada de texto

Neste exemplo, clicar no botão irá focar no input:

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Focus the input
      </button>
    </>
  );
}


Evitando recriar o conteúdo da ref

O React salva o valor inicial do ref uma vez e o ignora nas renderizações seguintes.

function Video() {
const playerRef = useRef(new VideoPlayer());
// ...

Embora o resultado de new VideoPlayer() seja usado somente para a renderização inicial, você ainda está chamando essa função em cada renderização. Isso pode ser um desperdício se estiver criando objetos caros.

Para resolver isso, você pode inicializar a ref assim, em vez disso:

function Video() {
const playerRef = useRef(null);
if (playerRef.current === null) {
playerRef.current = new VideoPlayer();
}
// ...

Normalmente, escrever ou ler ref.current durante a renderização não é permitido. No entanto, é aceitável neste caso porque o resultado é sempre o mesmo, e a condição só executa durante a inicialização, então é totalmente previsível.

Deep Dive

Como evitar null checks ao inicializar o useRef mais tarde

Se você usa um type checker e não quer sempre verificar por null, você pode tentar um padrão como este, em vez disso:

function Video() {
const playerRef = useRef(null);

function getPlayer() {
if (playerRef.current !== null) {
return playerRef.current;
}
const player = new VideoPlayer();
playerRef.current = player;
return player;
}

// ...

Aqui, a própria playerRef é nulável. No entanto, você deve ser capaz de convencer seu type checker de que não há caso em que getPlayer() retorne null. Então use getPlayer() em seus manipuladores de eventos.


Solução de Problemas

Eu não consigo obter uma ref para um componente customizado

Se você tentar passar uma ref para o seu próprio componente assim:

const inputRef = useRef(null);

return <MyInput ref={inputRef} />;

Você pode obter um erro no console:

Console
TypeError: Não é possível ler as propriedades de null

Por padrão, seus próprios componentes não expõem refs para os nós do DOM dentro deles.

Para corrigir isso, encontre o componente para o qual você quer obter uma ref:

export default function MyInput({ value, onChange }) {
return (
<input
value={value}
onChange={onChange}
/>
);
}

E então adicione ref para a lista de props que seu componente aceita e passe ref como uma prop para o componente embutido relevante como este:

function MyInput({ value, onChange, ref }) {
return (
<input
value={value}
onChange={onChange}
ref={ref}
/>
);
};

export default MyInput;

Então o componente pai pode obter uma ref para ele.

Leia mais sobre acessar nós DOM de outro componente.