Rendimiento de React más allá del memo manual: estructura y programación
Consejo de la época de los compiladores: gestiona el estado, separa el trabajo urgente, envía menos JavaScript y luego memoriza los puntos críticos medidos.
Durante años, el consejo sobre el rendimiento de React consistía por defecto en envolver todo con las APIs memo:
const value = useMemo(() => expensiveCalculation(data), [data]);
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);export default React.memo(Component);
function ProductList({ products, onSelect }) {
const processed = useMemo(
() => processProducts(products),
[products]
);
const handleSelect = useCallback(
(id) => onSelect(id),
[onSelect]
); return (
<List
products={processed}
onSelect={handleSelect}
/>
);
}
App
│
├── Header
├── Sidebar
├── Search
├── ProductList
└── Footer
function App() {
const [query, setQuery] = useState("");
// large component tree
}
App
│
├── Header
├── Sidebar
├── Search
│ └── query state
├── ProductList
└── Footer
const [query, setQuery] = useState("");
const [isPending, startTransition] = useTransition();
function handleChange(event) {
const value = event.target.value; setQuery(value); startTransition(() => {
setSearchResults(filterProducts(value));
});
}
User input
│
├── urgent ───────► keep UI responsive
│
└── non-urgent ───► transition
const AnalyticsDashboard = lazy(
() => import("./AnalyticsDashboard")
);
Initial JavaScript
│
▼
┌─────────────────────┐
│ Everything │
│ Dashboard │
│ Analytics │
│ Editor │
│ Admin │
└─────────────────────┘
Initial load
│
├── Core UI
│
└── Later
├── Analytics
├── Editor
└── Admin
"This component renders often."
│
▼
Add useMemo
"This component renders often."
│
▼
Why?
│
┌──────┼───────────┐
▼ ▼ ▼
State Expensive Large
flow work subtree
│ │ │
▼ ▼ ▼
Colocate Optimize Restructure
1. Measure
↓
2. Find the expensive work
↓
3. Fix component architecture
↓
4. Reduce unnecessary JavaScript
↓
5. Prioritize updates correctly
↓
6. Let React Compiler handle memoization
↓
7. Manually optimize only when evidence says you should
La memorización por sí sola no soluciona los problemas de lentitud en las aplicaciones. Un árbol perfectamente memorizado aún puede tener mal rendimiento debido a un estado excesivo, actualizaciones urgentes que realizan tareas no urgentes, o un JavaScript pesado en el hilo principal.
El compilador de React cambia la norma por defecto
El compilador automatiza muchos espacios de memorización. Esto dirige el esfuerzo humano hacia la estructura y la planificación, en lugar de colocar manualmente useMemo en todas partes.
Primero: coloca el estado cerca de donde se utiliza
Un estado de alto nivel en el árbol vuelve a renderizar los subárboles extensos. Coloca el estado junto con las hojas que lo necesitan; úsalo solo cuando sea necesario compartirlo.
Segundo: no hagas que las actualizaciones urgentes realicen trabajo no urgente
Mantén la capacidad de escritura y las animaciones responsivas. Pospone el trabajo no urgente mediante transiciones o valores diferidos para que las pulsaciones de teclado no se vean bloqueadas por filtros costosos.
Tercero: examina el JavaScript que estás enviando
Los bucles de sincronización grandes, los formateadores costosos y las listas ilimitadas dominan antes de que lo haga el reconciliador de React. Analiza el JavaScript, no solo lo que resaltan las herramientas de desarrollo de React.
Entonces, ¿cuándo deberías usar useMemo?
Sigue siendo útil para mantener la estabilidad referencial entre hijos que dejan de recibir props, y para cálculos puros realmente costosos, después de medir su impacto. No como solución por defecto para todos los valores.
La nueva mentalidad de rendimiento en React
Estructura → programación → enviar menos JavaScript → luego memorizar en microescala los puntos críticos. La memorización asistida por el compilador es una ayuda, no un sustituto del diseño.
Añada un presupuesto de rendimiento a las propuestas de cambio: tiempo necesario para la siguiente actualización visual del formulario principal, y una captura del perfilador de React para la ruta conocida por su alto consumo de recursos.
Las listas deben virtualizarse antes de memorizar cada fila. La memorización en una lista con 10,000 filas sigue siendo ineficaz.
Añada un presupuesto de rendimiento a las propuestas de cambio: tiempo necesario para la siguiente actualización visual del formulario principal, y una captura del perfilador de React para la ruta conocida por su alto consumo de recursos.
Las listas deben virtualizarse antes de memorizar cada fila. La memorización en una lista con 10,000 filas sigue siendo ineficaz.
Añada un presupuesto de rendimiento a las propuestas de cambio: tiempo necesario para la siguiente actualización visual del formulario principal, y una captura del perfilador de React para la ruta conocida por su alto consumo de recursos.
Las listas deben virtualizarse antes de memorizar cada fila. La memorización en una lista con 10,000 filas sigue siendo ineficaz.
Añadir un presupuesto de rendimiento a las PR: tiempo necesario para la siguiente actualización visual del formulario principal, y una captura del perfilador de React para la ruta conocida por su alto consumo de recursos.
Las listas deben virtualizarse antes de memorizar cada fila. Incluso al usar la función memo en una lista con 10,000 filas, se sigue perdiendo rendimiento.
Añadir un presupuesto de rendimiento a las PR: tiempo necesario para la siguiente actualización visual del formulario principal, y una captura del perfilador de React para la ruta conocida por su alto consumo de recursos.
Las listas deben virtualizarse antes de memorizar cada fila. Incluso al usar la función memo en una lista con 10,000 filas, se sigue perdiendo rendimiento.
Añadir un presupuesto de rendimiento a las PR: tiempo necesario para la siguiente actualización visual del formulario principal, y una captura del perfilador de React para la ruta conocida por su alto consumo de recursos.
Las listas deben virtualizarse antes de memorizar cada fila. Incluso al usar la función memo en una lista con 10,000 filas, se sigue perdiendo rendimiento.
Lecturas relacionadas
- Por qué React.memo sigue volviendo a renderizar: la identidad de la referencia en los props — Averigüe cómo React.memo compara los props, por qué las funciones inline, los objetos y los arrays lo invalidan, cómo estabilizar las referencias y por qué el perfilamiento debe realizarse antes de memorizar.
- React 19.3 más allá de las noticias: submitter, props de pantalla completa y tamaño del bundle — Un recorrido práctico por los cambios menores de React 19.3: la propiedad submitter, los props del evento fullscreen, las transiciones en paralelo, onReset, correcciones importantes de errores y el verdadero aumento de tamaño.