Kodokon kodokon.com

useRef y manipulación del DOM

Manipula el DOM y conserva valores de instancia con useRef, sin romper la pureza del render.

7 min · 3 preguntas

Abrir esta lección en Kodokon

useRef devuelve una caja mutable - un objeto con una única propiedad current - cuya identidad sobrevive a cada render. Dos diferencias fundamentales con el estado: modificar ref.current no provoca ningún re-render, y el cambio es visible de inmediato, sin esperar al siguiente render. De ahí se derivan dos familias de uso: referenciar un nodo del DOM, y almacenar un valor de instancia que debe sobrevivir a los renders sin dirigir la visualización.

JSX
import { useEffect, useRef } from "react";

function SearchField() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} type="search" />;
}
React adjunta el nodo a la ref después de confirmar el render.

Por el lado del valor de instancia, todo lo que deba persistir sin provocar un render pertenece a una ref: el id devuelto por setInterval, la instancia de una librería externa (un mapa, un editor, un reproductor de vídeo), o un valor de un render anterior. La regla de oro sigue siendo la misma: el renderizado debe ser una función pura de las props y del estado. Las refs se leen y se escriben en los efectos y en los manejadores de eventos, no durante el render.

JAVASCRIPT
import { useEffect, useRef } from "react";

function usePrevious(value) {
  const ref = useRef(undefined);

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}
El efecto se ejecuta después del render: la ref se queda un render por detrás.

Para exponer un nodo del DOM desde tu propio componente, pasa la ref a través de él: desde React 19, ref es una prop ordinaria de los componentes de función; antes de eso, pasar por forwardRef era obligatorio. Un último reflejo que cultivar: prefiere el enfoque declarativo cuando el estado baste para describir el resultado (una clase CSS, un atributo disabled). Reserva las refs para el terreno que React no cubre: el foco, la selección de texto, medir un elemento, el scroll, la reproducción de medios.

JSX
import { useRef } from "react";

function TextField({ ref, ...props }) {
  return <input ref={ref} {...props} />;
}

function Form() {
  const fieldRef = useRef(null);

  return (
    <>
      <TextField ref={fieldRef} />
      <button onClick={() => fieldRef.current.focus()}>
        Give focus
      </button>
    </>
  );
}
Desde React 19, ref se pasa como cualquier otra prop.

Prueba de conocimientos

Comprueba que has retenido los puntos clave de esta lección.

  1. ¿Qué diferencia fundamental separa useRef de useState para almacenar un valor?
    • Modificar ref.current no provoca ningún re-render, a diferencia de una actualización de estado
    • useRef conserva su valor después de que el componente se desmonte
    • useRef solo puede almacenar nodos del DOM
    • Las refs se comparten entre todas las instancias de un componente
  2. ¿Por qué acceder a inputRef.current en useEffect en lugar de durante el render?
    • Porque useEffect agrupa los accesos al DOM para mejorar el rendimiento
    • Porque las refs quedan bloqueadas para lectura durante el render
    • Porque React solo adjunta el nodo después del commit: durante el primer render, current sigue siendo null
  3. ¿Qué devuelve usePrevious(value) en el primer render?
    • El valor actual de value
    • undefined, porque el efecto que escribe en la ref aún no se ha ejecutado
    • null
    • El valor del siguiente render