Cómo evitar renders innecesarios en React

Cómo evitar renders innecesarios en React

El rendimiento es un aspecto fundamental al desarrollar aplicaciones con React. Aunque React está diseñado para actualizar la interfaz de forma eficiente, una aplicación mal estructurada puede generar renders innecesarios que afectan la velocidad y la experiencia del usuario.

Un render ocurre cuando React vuelve a ejecutar un componente para determinar qué debe cambiar en la interfaz. No todos los renders son un problema, pero cuando se producen con demasiada frecuencia pueden aumentar el consumo de recursos.

¿Por qué ocurren renders innecesarios?

Una de las causas más comunes es modificar el estado de un componente con demasiada frecuencia. También pueden producirse cuando un componente padre se renderiza y provoca que sus componentes hijos vuelvan a ejecutarse, incluso cuando sus propiedades no han cambiado.

Por ejemplo:

function Usuario({ nombre }) {
  console.log("Render Usuario");
  return <h2>{nombre}</h2>;
}

function App() {
  const [contador, setContador] = useState(0);

  return (
    <>
      <button onClick={() => setContador(contador + 1)}>
        {contador}
      </button>

      <Usuario nombre="Johan" />
    </>
  );
}

Cada vez que cambia contador, App se renderiza nuevamente y Usuario también puede volver a renderizarse.

Utilizar React.memo

Una de las herramientas más útiles es React.memo. Este permite memorizar un componente y evitar que se vuelva a renderizar si sus propiedades no han cambiado.

const Usuario = React.memo(function Usuario({ nombre }) {
  return <h2>{nombre}</h2>;
});

Ahora, si nombre continúa siendo el mismo, React puede evitar un render adicional cuando el componente padre cambie.

useMemo para cálculos costosos

useMemo permite guardar el resultado de un cálculo y volver a ejecutarlo únicamente cuando cambien sus dependencias.

const resultado = useMemo(() => {
  return productos.filter(producto => producto.precio > 100);
}, [productos]);

Esto resulta especialmente útil cuando trabajamos con listas grandes o cálculos que requieren bastante procesamiento.

useCallback para funciones

Las funciones creadas dentro de un componente se generan nuevamente durante cada render. Cuando se pasan como propiedades a componentes memorizados, esto puede provocar renders adicionales.

useCallback permite conservar la misma referencia de una función mientras sus dependencias no cambien:

const eliminarProducto = useCallback((id) => {
  setProductos(productos =>
    productos.filter(producto => producto.id !== id)
  );
}, []);

Evita optimizar sin medir

No todos los renders innecesarios tienen un impacto importante. Utilizar memo, useMemo y useCallback indiscriminadamente también puede aumentar la complejidad del código.

Lo recomendable es identificar primero los componentes que realmente presentan problemas de rendimiento. Herramientas como React DevTools Profiler permiten analizar qué componentes se renderizan, cuánto tiempo tardan y qué cambios provocaron el render.

Buenas prácticas

Para mejorar el rendimiento de una aplicación React:

  • Mantén el estado lo más cerca posible de los componentes que lo necesitan.
  • Evita crear objetos y funciones innecesariamente.
  • Utiliza React.memo cuando realmente aporte beneficios.
  • Usa useMemo para cálculos costosos.
  • Utiliza useCallback cuando necesites mantener referencias estables.
  • Divide componentes demasiado grandes.
  • Analiza el rendimiento antes y después de realizar optimizaciones.

La clave no es eliminar todos los renders, sino conseguir que React renderice solamente lo necesario. Con una buena estructura de componentes y el uso adecuado de las herramientas de optimización, es posible crear aplicaciones React más rápidas, escalables y eficientes.

Te puede interesar...

Deja un comentario