Guía Completa de useRef en React 🪝

¿Qué es useRef?

useRef es un Hook de React que proporciona una forma de crear una referencia mutable que persiste durante todo el ciclo de vida del componente. Es como una “caja” que puede mantener un valor mutable en su propiedad .current.

  Mutable

En React, un valor mutable es cualquier valor o referencia que puede cambiar sin la necesidad de ser recreado, como un objeto, arreglo o instancia de una clase. Esto es importante porque React espera que los datos que provocan cambios en la UI sean inmutables para que pueda detectar cambios fácilmente y actualizar la interfaz solo cuando sea necesario.

  Características principales de useRef

  • 🔄 El valor persiste entre renderizados
  • 🎯 Modificar .current no causa re-renderizados
  • 🧩 Útil para acceder al DOM directamente
  • 📦 Mantiene valores entre renderizados sin causar actualizaciones

Sintaxis básica:

jsx
const refContainer = useRef(valorInicial);

¿Cuándo usar useRef?

useRef es especialmente útil en los siguientes escenarios:

  Nota

  1. 🎯 Acceder a elementos DOM directamente
  2. 🕒 Guardar valores previos
  3. ⏱️ Mantener variables mutables (como intervalos o timeouts)
  4. 🔢 Contar renderizados sin causar actualizaciones

Casos prácticos


1. Manipulación del DOM

Un caso común es manipular elementos del DOM, como dar foco a un input. Este componente permite enfocar el campo de texto (input) programáticamente usando useRef. Al hacer clic en el botón, la función focusInput llama a inputRef.current.focus(), moviendo el cursor al campo de entrada.

jsx
function FocusInput() {
const inputRef = useRef(null);

const focusInput = () => {
  inputRef.current.focus();
};

return (
  <>
    <input ref={inputRef} type="text" />
    <button onClick={focusInput}>Dar foco</button>
  </>
);
}

2. Obtener la referencia de un elemento HTML como una lista <select> usando useRef

Para obtener la referencia de un elemento HTML como una lista <select> usando useRef, sigue este ejemplo. Así, podrás acceder directamente al elemento, leer su valor o manipularlo sin desencadenar re-renderizados innecesarios.

jsx
import { useRef } from 'react';

function SelectPaises() {
const selectRef = useRef(null);

const handleSelectChange = () => {
  alert(`País seleccionado: ${selectRef.current.value}`);
};

return (
  <div>
    <select ref={selectRef} onChange={handleSelectChange}>
      <option value="venezuela">Venezuela</option>
      <option value="mexico">México</option>
      <option value="colombia">Colombia</option>
      <option value="peru">Perú</option>
      <option value="ecuador">Ecuador</option>
      <option value="bolivia">Bolivia</option>
      {/* Agrega más países aquí */}
    </select>
    <button onClick={() => alert(`País actual: ${selectRef.current.value}`)}>
      Mostrar país actual
    </button>
  </div>
);
}
  Explicación

  • Definir la referencia: const selectRef = useRef(null); crea una referencia que apunta al elemento <select>.
  • Asignar la referencia: Se asigna a la propiedad ref del <select> para que selectRef.current apunte al elemento en el DOM.
  • Usar la referencia: Con selectRef.current.value, puedes acceder al valor seleccionado sin necesidad de manejar el estado de React. El botón, por ejemplo, muestra el valor actual seleccionado en un alert.

3. Referenciar elementos DOM para animaciones

Puedes usar useRef para animar un elemento de manera directa.

jsx
import { useRef } from 'react';

function AnimateElement() {
const boxRef = useRef(null);

const handleAnimate = () => {
  boxRef.current.style.transition = 'transform 1s';
  boxRef.current.style.transform = 'translateX(200px)';
};

return (
  <div>
    <div ref={boxRef} style={{ width: '100px', height: '100px', backgroundColor: 'blue' }} />
    <button onClick={handleAnimate}>Mover Caja</button>
  </div>
);
}

4. Mantener el valor anterior de una variable

Útil para comparar valores actuales con anteriores. Este componente en React muestra un contador (count) y su valor anterior (prevCountRef.current). Cada vez que count cambia, useEffect actualiza el valor anterior para compararlo con el actual en el siguiente render.

javascript
function ComponenteConHistorial() {
const [count, setCount] = useState(0);
const prevCountRef = useRef();

useEffect(() => {
  prevCountRef.current = count;
}, [count]);

return (
  <div>
    <p>Valor actual: {count}</p>
    <p>Valor anterior: {prevCountRef.current}</p>
    <button onClick={() => setCount(c => c + 1)}>
      Incrementar
    </button>
  </div>
);
}

5. Gestión de intervalos

useRef es perfecto para manejar intervalos y timeouts. Este código implementa un temporizador que incrementa un contador cada segundo usando setInterval. El useRef almacena el identificador del intervalo, lo que permite detenerlo limpiamente al desmontar el componente o al hacer clic en el botón “Detener”.

javascript
function Temporizador() {
const [count, setCount] = useState(0);
const intervalRef = useRef();

useEffect(() => {
  intervalRef.current = setInterval(() => {
    setCount(c => c + 1);
  }, 1000);

  return () => clearInterval(intervalRef.current);
}, []);

return (
  <div>
    <h1>Contador: {count}</h1>
    <button onClick={() => clearInterval(intervalRef.current)}>
      Detener
    </button>
  </div>
);
}

6. Contar el número de renders de un componente

Para debugging o monitoreo de rendimiento. Lleva la cuenta de cuántas veces se ha renderizado el componente, sin provocar re-renderizados adicionales.

La función ContadorRenders cuenta cuántas veces se renderiza el componente, usando useRef para almacenar el número de renders sin provocar re-renders adicionales. Cada render incrementa renderCount.current en 1, y el botón permite actualizar el estado, desencadenando nuevos renders.

javascript
function ContadorRenders() {
const [estado, setEstado] = useState(0);
const renderCount = useRef(0);

useEffect(() => {
  renderCount.current += 1;
});

return (
  <div>
    <p>Número de renders: {renderCount.current}</p>
    <button onClick={() => setEstado(s => s + 1)}>
      Actualizar estado
    </button>
  </div>
);
}

Mejores prácticas 👌


  1. Inicialización: Siempre inicializa useRef con un valor inicial apropiado
javascript
const inputRef = useRef(null); // Para refs DOM
const countRef = useRef(0);    // Para valores numéricos
  1. Limpieza: Limpia los intervalos y timeouts en el cleanup de useEffect
javascript
useEffect(() => {
   const id = setInterval(() => {}, 1000);
   return () => clearInterval(id);
 }, []);
  1. Acceso al DOM: Verifica que la ref existe antes de usarla
javascript
if (myRef.current) {
   myRef.current.focus();
 }

⚠️ Advertencias y consideraciones

  Advertencias y consideraciones

  1. No uses useRef para valores que deban causar re-renderizados
  2. Evita modificar .current durante el renderizado
  3. No confíes en la ref para valores que necesiten sincronización con el estado
  4. Usa refs DOM solo cuando sea necesario.

  Conclusión

useRef es una herramienta poderosa en React cuando se usa correctamente. Es perfecta para:

  • Manipulación directa del DOM
  • Almacenamiento de valores que no requieren re-renderizado
  • Gestión de timers y valores mutables
  • Debugging y monitoreo de rendimiento

Documentación Oficial 📚