useRef es un React Hook que te permite referenciar un valor que no es necesario para el renderizado.

const ref = useRef(initialValue)

Uso

Referenciar un valor con una referencia

Llame a useRef en el nivel superior de su componente para declarar uno o más referencias.

import { useRef } from 'react';

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

useRef devuelve una referencia al objeto con una sola propiedad actual Establecida inicialmente con el Valor inicial que usted proporcionó.

En los siguientes renderizados, useRef devolverá el mismo objeto. Puedes cambiar su propiedad actual para almacenar información y leerla más tarde. Esto puede recordarte a estado, pero hay una diferencia importante.

El cambio de una referencia no provoca una nueva renderización. Esto significa que las referencias son perfectas para almacenar información que no afecta a la salida visual de su componente. Por ejemplo, si necesita almacenar un ID de intervalo y recuperarlo más tarde, puedes ponerlo en una referencia. Para actualizar el valor dentro de la referencia, es necesario cambiar manualmente supropiedad actual:

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

Más tarde, puedes leer el ID de ese intervalo desde la referencia para poder llamar a borrar ese intervalo:

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

Al utilizar una referencia, te aseguras de que:

  • Puedes almacenar información entre renderizados (a diferencia de las variables regulares, que se reinician en cada renderizado).
  • El cambio de la misma no desencadena un renderizado (a diferencia de las variables de estado, que desencadenan un renderizado).
  • La información es local para cada copia de su componente (a diferencia de las variables externas, que son compartidas).

El cambio de una referencia no desencadena un renderizado, por lo que las referencias no son apropiadas para almacenar información que se quiere mostrar en la pantalla. Utiliza el estado para eso. Leer más sobre [elegir entre useRef y useState].(/learn/referencing-values-with-refs#differences-between-refs-and-state)

Ejemplos de referencia a un valor con useRef

Ejemplo 1 de 2:
Contador de clics

Este componente utiliza una referencia para llevar la cuenta de las veces que se ha pulsado el botón. Tenga en cuenta que está bien usar una referencia en lugar de un estado aquí porque el recuento de clics sólo se lee y se escribe en un controlador de eventos.

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}>
      Haz clic en mí!
    </button>
  );
}

Si muestra {ref.current} en el JSX, el número no se actualizará al hacer clic. Esto se debe a que el establecimiento de ref.current no desencadena un renderizado. La información que se utiliza para el renderizado debe ser el estado en su lugar.

Atención

No escriba ni lea ref.current durante la renderización.

React espera que el cuerpo de tu componente se comporte como una función pura:

  • Si las entradas (props, state, y context) son iguales, debería devolver exactamente el mismo JSX.
  • Llamarla en un orden diferente o con argumentos diferentes no debería afectar a los resultados de otras llamadas.

Leer o escribir una referencia durante el renderizado rompe estas expectativas.

function MyComponent() {
// ...
// 🚩 No escriba una referencia durante el renderizado
myRef.current = 123;
// ...
// 🚩 No leer una referencia durante el renderizado
return <h1>{myOtherRef.current}</h1>;
}

Puedes leer o escribir referencias desde manejadores de eventos o efectos en su lugar.

function MyComponent() {
// ...
useEffect(() => {
// ✅ Se pueden leer o escribir referencias en efectos
myRef.current = 123;
});
// ...
function handleClick() {
// ✅ Puedes leer o escribir referencias en los manejadores de eventos
doSomething(myOtherRef.current);
}
// ...
}

Si tiene que leer o escribir algo durante la renderizacion, utilice el estado en su lugar.

Si rompes estas reglas, tu componente puede seguir funcionando, pero la mayoría de las nuevas características que estamos añadiendo a React se basarán en estas expectativas. Lee más sobre mantener tus componentes puros.


Manipulación del DOM con una referencia

Es particularmente común utilizar una referencia para manipular el [DOM].(https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API) React tiene soporte incorporado para esto.

En primer lugar, declare una referencia al objeto con un valor inicial de null:

import { useRef } from 'react';

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

Entonces pasa tu objeto de referencia como el atributo ref al JSX del nodo DOM que quieres manipular:

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

Después de que React cree el nodo DOM y lo ponga en la pantalla, React establecerá la propiedad actual de su objeto de referencia a ese nodo DOM. Ahora puedes acceder al nodo DOM de <input> y llamar a métodos como focus():

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

React devolverá la propiedad actual a null cuando el nodo sea eliminado de la pantalla.

Más información sobre lamanipulación del DOM con referencias.

Ejemplos de manipulación del DOM con useRef

Ejemplo 1 de 4:
Enfocar una entrada de texto

En este ejemplo, al hacer clic en el botón se centrará la entrada:

import { useRef } from 'react';

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

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

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Centrar la entrada
      </button>
    </>
  );
}


Evitar la recreación del contenido de las referencias

React guarda el valor inicial de la referencia una vez y lo ignora en los siguientes renderizados.

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

Aunque el resultado de new VideoPlayer() sólo se utiliza para el renderizado inicial, todavía estás llamando a esta función en cada renderizado. Esto puede ser un desperdicio si está creando objetos costosos.

Para solucionarlo, puedes inicializar la referencia de esta manera:

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

Normalmente, no se permite escribir o leer ref.current durante el renderizado. Sin embargo, está bien en este caso porque el resultado es siempre el mismo, y la condición sólo se ejecuta durante la inicialización por lo que es totalmente predecible.

Deep Dive

Cómo evitar la comprobación de nulos al inicializar useRef posteriormente

Si utilizas un comprobador de tipos y no quieres comprobar siempre la existencia de null, puedes probar con un patrón como éste:

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

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

// ...

Aquí, el propio playerRef es anulable. Sin embargo, deberías ser capaz de convencer a tu comprobador de tipos de que no hay ningún caso en el que getPlayer() devuelva null. Entonces usa getPlayer() en tus manejadores de eventos.


Referencia

useRef(valorInicial)

Llame a useRef en el nivel superior de su componente para declarar una referencia.

import { useRef } from 'react';

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

Ver ejemplos de valores de referencia y [manipulación de DOM].(#examples-dom)

Parámetros

  • ValorInicial: El valor que quieres que tenga inicialmente la propiedad actual del objeto de referencia. Puede ser un valor de cualquier tipo. Este argumento se ignora después del renderizado inicial.

Devuelve

useRef devuelve un objeto con una sola propiedad:

  • actual: Inicialmente, se establece en el ValorInicial que has pasado. Más tarde puedes establecerlo a otra cosa. Si pasas el objeto de referencia a React como un atributo referencia a un nodo JSX, React establecerá su propiedad current.

En los siguientes renderizados, useRef devolverá el mismo objeto.

Advertencias

  • Puedes mutar la propiedad ref.current. A diferencia del estado, es mutable. Sin embargo, si contiene un objeto que se utiliza para la representación (por ejemplo, un pedazo de su estado), entonces usted no debe mutar ese objeto.
  • Cuando cambias la propiedad ref.current, React no vuelve a renderizar tu componente. React no se da cuenta de cuándo la cambias porque una referencia es un objeto JavaScript plano.
  • No escriba ni lea ref.current durante el renderizado, excepto para la [inicialización].(#avoiding-recreating-the-ref-contents) Esto hace que el comportamiento de su componente sea impredecible.
  • En el modo estricto, React llamará a la función de tu componente dos veces para ayudarte a encontrar impurezas accidentales. Este es un comportamiento sólo de desarrollo y no afecta a la producción. Esto significa que cada objeto ref se creará dos veces, y una de las versiones se descartará. Si la función de su componente es pura (como debería ser), esto no debería afectar a la lógica de su componente.

Solución de problemas

No puedo obtener una referencia a un componente personalizado

Si intentas pasar una referencia a tu propio componente de esta manera

const inputRef = useRef(null);

return <MyInput ref={inputRef} />;

Es posible que aparezca un error en la consola:

Console
Advertencia: Los componentes de la función no pueden recibir referencias. Los intentos de acceder a esta referencia fallarán. ¿Quiere decir que utiliza React.forwardRef()?

Por defecto, tus propios componentes no exponen las referencias a los nodos del DOM que hay dentro de ellos.

Para solucionarlo, busca el componente del que quieres obtener una referencia:

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

Y luego envolverlo en forwardRef así:

import { forwardRef } from 'react';

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

export default MyInput;

Entonces el componente padre puede obtener una referencia a él.

Más información sobre el acceso a los nodos DOM de otro componente.