Optimización de Rendimiento
React es rápido por defecto gracias al Virtual DOM, pero en apps grandes pueden surgir problemas: componentes que se re-renderizan innecesariamente, cálculos que se repiten en cada render, o el bundle inicial que tarda demasiado en descargarse.
React.memo envuelve un componente y lo protege: si las props que recibe no cambiaron desde el último render, React omite el re-render y usa la versión en caché. Es el escudo para componentes que reciben siempre los mismos datos pero están dentro de un componente padre que sí cambia.
Code splitting con React.lazy y Suspense divide el bundle de JavaScript en trozos. Por defecto, todo el código de la app se descarga en un solo archivo al cargar por primera vez. Con lazy(), cada ruta o componente pesado tiene su propio trozo que solo se descarga cuando el usuario lo necesita por primera vez.
El resultado es una carga inicial mucho más rápida. Suspense muestra un fallback (spinner o skeleton) mientras el trozo se descarga. Usa React DevTools Profiler para identificar exactamente qué componentes son lentos antes de optimizar.
import { memo, useMemo, useCallback, useState } from "react";
// React.memo - componente no se re-renderiza si props no cambian
const ItemLista = memo(function ItemLista({ item, onEliminar }) {
console.log("Renderizando:", item.nombre);
return (
<li>
{item.nombre}
<button onClick={() => onEliminar(item.id)}>x</button>
</li>
);
});
function Lista() {
const [items, setItems] = useState([
{ id: 1, nombre: "Item 1" },
{ id: 2, nombre: "Item 2" }
]);
const [contador, setContador] = useState(0);
// Sin useCallback, nueva función en cada render → memo no funciona
const eliminar = useCallback((id) => {
setItems(prev => prev.filter(i => i.id !== id));
}, []); // Referencia estable
// Sin useMemo, se calcula en cada render
const stats = useMemo(() => ({
total: items.length,
nombres: items.map(i => i.nombre).join(", ")
}), [items]);
return (
<div>
<button onClick={() => setContador(c => c + 1)}>Clicks: {contador}</button>
<p>Total: {stats.total} - {stats.nombres}</p>
<ul>
{items.map(item => (
<ItemLista key={item.id} item={item} onEliminar={eliminar} />
))}
</ul>
</div>
);
}
// React.lazy y Suspense - Code Splitting
import { lazy, Suspense } from "react";
const PaginaPesada = lazy(() => import("./PaginaPesada"));
function App() {
return (
<Suspense fallback={<div>Cargando...</div>}>
<PaginaPesada />
</Suspense>
);
}
Practica esta lección
Resuelve los ejercicios del curso de React en la app, gratis y con corrección automática.
Empezar a practicar