DevPath · Aprende a programar ESPTEN

Hooks personalizados y rendimiento

Rendimiento: por qué re-renderiza React

¿Por qué se vuelve a renderizar un componente?

React vuelve a renderizar un componente cuando:

Ese tercer punto es clave: por defecto, si un padre re-renderiza, todos sus hijos re-renderizan en cascada. Casi siempre eso es barato y no pasa nada. Pero cuando un subárbol es pesado, conviene tener herramientas para evitar trabajo innecesario.

React.memo: memoiza un componente

React.memo envuelve un componente para que solo se re-renderice si sus props cambian (comparación superficial). Si el padre repinta pero las props del hijo son las mismas, React reutiliza el render anterior:

const ListaPesada = React.memo(function ListaPesada({ items }) {
  // render costoso...
  return <ul>{items.map((i) => <li key={i}>{i}</li>)}</ul>;
});

Solo es útil si las props se mantienen estables entre renders. Ahí entran los dos hooks siguientes.

useMemo: memoiza un valor calculado

useMemo recuerda el resultado de un cálculo y solo lo recalcula si cambia alguna de sus dependencias. Ideal para cálculos caros:

const ordenados = useMemo(() => {
  return [...items].sort((a, b) => a - b); // cálculo caro
}, [items]); // solo se recalcula si 'items' cambia

Sin useMemo, ese sort correría en cada render. Con él, solo cuando items cambia.

useCallback: memoiza una función

En cada render se crean funciones nuevas. Si pasas una función como prop a un componente envuelto en React.memo, esa prop "cambia" siempre y la memoización se rompe. useCallback estabiliza la identidad de la función:

const manejarClick = useCallback(() => {
  setSeleccion(id);
}, [id]); // misma función mientras 'id' no cambie

useCallback(fn, deps) es equivalente a useMemo(() => fn, deps): uno memoiza la función, el otro su resultado.

Regla mental: useMemo para valores, useCallback para funciones, React.memo para componentes. Los tres comparan dependencias/props para decidir si pueden saltarse trabajo.

Ejemplos

useMemo evita recalcular si las dependencias no cambian

let calculos = 0;
function calcularCaro(n) { calculos++; return n * 2; }
// Render 1
const a = calcularCaro(21);
// Render 2 con la misma entrada -> con useMemo NO se recalcularía
console.log("resultado:", a, "| veces calculado:", calculos);
Pon esto en práctica

DevPath es un curso práctico: aquí lees la teoría; en la app la pones en práctica con ejercicios que se ejecutan de verdad, sin conexión.

Empezar gratis en la app →
← Hooks personalizados: lógica con estado reutilizableCuándo (y cuándo no) optimizar →