Inicio > Cursos > React > useRef, useMemo y useCallback
ReactHooks EsencialesLección 7 de 21

useRef, useMemo y useCallback

useRef es como una caja con tapa: guarda un valor en .current que puedes modificar sin que React se entere ni re-renderice.

Es perfecta para acceder al DOM directamente (enfocar un input, medir su tamaño) o para guardar valores que el componente necesita internamente pero que no deben aparecer en pantalla, como el ID de un intervalo o la cantidad de renders. Cambiar .current no dispara un nuevo render, a diferencia de setState.

useMemo y useCallback son hermanos que guardan resultados en caché. useMemo guarda el resultado de un cálculo costoso: "si los datos no cambiaron, devuelve el número guardado sin recalcular". useCallback guarda la referencia de una función: sin él, cada render crea una nueva función con diferente dirección de memoria, lo que hace que React.memo no pueda detectar que "es la misma función" y re-renderice igual. Úsalos solo cuando mides un problema real de rendimiento con React DevTools Profiler.

import { useRef, useMemo, useCallback, useState } from "react";

function EjemplosHooks() {
  const [lista, setLista] = useState([1,2,3,4,5,6,7,8,9,10]);
  const [filtro, setFiltro] = useState(0);
  
  // useRef - referencia al DOM (no dispara re-renders)
  const inputRef = useRef(null);
  const enfocarInput = () => inputRef.current.focus();
  
  // useRef para guardar valores sin re-renderizar
  const contadorRenders = useRef(0);
  contadorRenders.current++;
  
  // useMemo - memoiza el resultado de cálculos
  // Solo recalcula cuando cambia [lista, filtro]
  const listaFiltrada = useMemo(() => {
    console.log("Filtrando...");  // Solo cuando cambia
    return lista.filter(n => n > filtro);
  }, [lista, filtro]);
  
  // useMemo para objetos (evitar re-renders innecesarios)
  const estilos = useMemo(() => ({
    color: filtro > 5 ? "red" : "green"
  }), [filtro]);
  
  // useCallback - memoiza funciones (referencia estable)
  const agregar = useCallback(() => {
    setLista(prev => [...prev, prev.length + 1]);
  }, []); // Sin deps = misma función siempre
  
  return (
    <div>
      <input ref={inputRef} placeholder="Ingresa algo" />
      <button onClick={enfocarInput}>Enfocar</button>
      <input
        type="number"
        value={filtro}
        onChange={e => setFiltro(Number(e.target.value))}
      />
      <p style={estilos}>Renders: {contadorRenders.current}</p>
      <ul>{listaFiltrada.map(n => <li key={n}>{n}</li>)}</ul>
    </div>
  );
}
Consejo⚡ No abuses de useMemo y useCallback. La optimización prematura es mala. Úsalos solo cuando mides un problema real de rendimiento.
← useContext - Estado GlobalCustom Hooks →

Practica esta lección

Resuelve los ejercicios del curso de React en la app, gratis y con corrección automática.

Empezar a practicar