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.memocuando realmente aporte beneficios. - Usa
useMemopara cálculos costosos. - Utiliza
useCallbackcuando 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.

