Inicio / Artículos / La velocidad de React comienza con la organización del árbol de componentes.

La velocidad de React comienza con la organización del árbol de componentes.

Las re-renderizaciones no son el enemigo: lo es la propagación amplia del estado. Mueva las fuentes hacia los nodos periféricos antes de realizar memorización a nivel micro.

1699 palabras

React hace lo que exige el diseño en forma de árbol. Cuando una aplicación parece lenta, suele ser porque el framework sigue un camino amplio de propagación del estado/actualización, y no porque haya algún fallo misterioso.

El volver a renderizar no es el enemigo

Los renders son lo que mantiene consistente la interfaz de usuario. El verdadero enemigo es el trabajo innecesario que se realiza en grandes subárboles con cada tecla pulsada.

// ❌ count lives in Parent — expensive siblings re-render on every click
function Parent() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
      <ExpensiveComponent />
      <AnotherExpensiveComponent />
    </div>
  );
}
// ✅ count lives in Counter — expensive siblings are untouched
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <button onClick={() => setCount(c => c + 1)}>
      Count: {count}
    </button>
  );
}

function Parent() {
  return (
    <div>
      <Counter />
      <ExpensiveComponent />
      <AnotherExpensiveComponent />
    </div>
  );
}
// ❌ SearchLayout owns state — ExpensiveList re-renders on every keystroke
function SearchLayout() {
  const [query, setQuery] = useState('');

  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      <ExpensiveList />
    </div>
  );
}
/* ✅ StatefulInput receives expensive content as children
 — its reference stays stable */
function StatefulInput({ children }) {
  const [query, setQuery] = useState('');
  return (
    <div>
      <input value={query} onChange={e => setQuery(e.target.value)} />
      {children}
    </div>
  );
}

function SearchLayout() {
  return (
    <StatefulInput>
      <ExpensiveList />
    </StatefulInput>
  );
}

Dónde debe detenerse la propagación

Mover el origen del estado

Coloca el estado junto a los componentes que lo escriben y lo leen. El texto preliminar de un formulario no necesita estar en la raíz de la aplicación.

Obstruir el camino

Los hijos que reciben propiedades estables pueden evitar este problema. La composición y el uso de hijos como slots suelen ser mejores que la memorización generalizada.

El árbol como decisión de diseño

La organización es una elección arquitectónica: las carpetas de funcionalidades, la división entre contenedores y elementos de presentación, y los proveedores locales limitan el alcance de las actualizaciones.

Partiendo del árbol

Antes de recurrir a microoptimizaciones, determine qué estado debe ubicarse dónde y qué subárboles deben permanecer estables durante actualizaciones frecuentes. La mayoría de los problemas relacionados con la lentitud de React se deben a problemas en el árbol estructural.

Haga un perfil primero, luego reorganice; guarde en memoria los resultados al final.

Los proveedores de contexto forman parte del árbol: un megacontexto que cambia en cada renderizado anula los efectos de la memorización de nodos. Divida los contextos según la frecuencia de actualizaciones.

La división del código a nivel de ruta reduce el tamaño del árbol que se procesa al pintar la pantalla por primera vez; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas que están fuera de la pantalla en lugar de tratar de sincronizar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación generalizada bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde reside el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según su frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas fuera de la pantalla en lugar de reconciliar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación generalizada bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde reside el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según la frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas fuera de la pantalla en lugar de reconciliar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación generalizada bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde reside el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según la frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas fuera de la pantalla en lugar de reconciliar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación generalizada bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde reside el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según la frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas fuera de la pantalla en lugar de reconciliar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación generalizada bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde reside el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según su frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas fuera de la pantalla en lugar de reconciliar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación generalizada bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde reside el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según su frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas fuera de la pantalla en lugar de reconciliar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación generalizada bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde reside el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según la frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

La virtualización de listas es como una cirugía en el árbol: desmonte las filas fuera de la pantalla en lugar de reconciliar miles de nodos inactivos.

Propiedad de los documentos: qué equipo es responsable del estado de cada subárbol. Los almacenes globales compartidos reproducen el problema de propagación general bajo otro nombre.

Utilice los tiempos de confirmación del React Profiler antes y después de un cambio en el estado; mantenga la diferencia en la solicitud de revisión para su análisis.

Los componentes del servidor y las islas del cliente cambian el lugar donde se encuentra el árbol, pero la disciplina de propagación sigue siendo aplicable en las islas del cliente.

Los proveedores de contexto forman parte del árbol: un mega-contexto que cambia en cada renderizado anula la memorización de las hojas. Divida los contextos según la frecuencia de actualización.

La división del código a nivel de ruta reduce el árbol por el cual se paga en la primera pintura; combínelo con el estado local para mantener las navegaciones ligeras.

Los proveedores que se actualizan con cada tecla presionada deben envolver únicamente a los consumidores que necesitan esa frecuencia, y no a toda la estructura de la página.

Los datos derivados deben encontrarse en selectores o hijos memorizados, y no reflejarse en el estado de los elementos hermanos, lo que generaría más renderizaciones.

Visualice el árbol: dibuje cajas para los propietarios del estado y flechas para las propiedades. Las ramificaciones amplias desde la raíz son una señal típica de problemas.

Las características concurrentes ayudan a gestionar la urgencia, pero no pueden solucionar un componente “dios” que controle todos los campos de un asistente complejo.

Táctica de migración: mueva una hoja de la isla de estado hacia afuera por cada PR, utilizando un perfilador antes y después de realizar los cambios.

Los proveedores que se actualizan con cada tecla presionada solo deben envolver a los consumidores que necesiten esa frecuencia, y no a toda la estructura de la página.

Los datos derivados deben encontrarse en selectores o hijos memorizados, y no reflejarse en el estado de los elementos hermanos, lo que generaría más renderizaciones.

Visualice el árbol: dibuje cajas para los propietarios del estado y flechas para las propiedades. Las ramificaciones amplias desde la raíz son una señal típica de problemas.

Las características concurrentes ayudan con la urgencia, pero no pueden solucionar un componente “dios” que controla todos los campos de un asistente complejo.

Táctica de migración: mover una isla de estado hacia las hojas por cada PR, utilizando un perfilador antes y después de su integración.

Los proveedores que se actualizan con cada tecla presionada deben envolver únicamente a los consumidores que necesitan esa frecuencia, y no toda la estructura de la página.

Los datos derivados deben encontrarse en selectores o hijos memorizados, y no reflejarse en estados hermanos que generen más renderizaciones.

Visualice el árbol: dibuje cuadros para los propietarios de estado y flechas para las propiedades. Las ramificaciones amplias desde la raíz suelen ser una señal de problema.

Las características concurrentes ayudan con la urgencia, pero no pueden solucionar un componente “dios” que controla todos los campos de un asistente complejo.

Táctica de migración: mover una isla de estado hacia las hojas por cada PR, utilizando un perfilador antes y después de su integración.

Los proveedores que se actualizan con cada tecla presionada deben envolver únicamente a los consumidores que necesitan esa frecuencia, y no toda la estructura de la página.

Los datos derivados deben encontrarse en selectores o hijos memorizados, y no reflejarse en el estado de los elementos hermanos, lo que generaría más renderizaciones.

Visualice el árbol: dibuje cuadros para los propietarios del estado y flechas para las props. Un amplio despliegue desde la raíz es una señal típica de este problema.

Lecturas relacionadas

  • Guía de entrevista para React: ganchos, renderizado y lo que preguntan las grandes compañías — DOM virtual, trampas con los ganchos, rendimiento, gestión de estado, React 18, ejercicios de codificación en vivo y cómo explicar las razones detrás de los re-renderizos.
  • Permitir que React useReducer mantenga su estado en sessionStorage — Guardar y restaurar el estado del reducer entre recargas mediante mecanismos de serialización para que la interfaz siga funcionando tras un refresh sin que se filtren datos confidenciales en el almacenamiento.