Ir al contenido principal

Rendimiento

Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Preguntas Frecuentes de Redux: Rendimiento

¿Cómo "escala" Redux en términos de rendimiento y arquitectura?

Aunque no hay una única respuesta definitiva, en la mayoría de los casos esto no debería ser motivo de preocupación.

El trabajo realizado por Redux generalmente se divide en varias áreas: procesar acciones en middleware y reducers (incluyendo duplicación de objetos para actualizaciones inmutables), notificar a los suscriptores después de despachar acciones, y actualizar componentes de UI según los cambios de estado. Si bien es ciertamente posible que cada una de estas áreas se convierta en una preocupación de rendimiento en situaciones suficientemente complejas, no hay nada inherentemente lento o ineficiente en la implementación de Redux. De hecho, React Redux en particular está altamente optimizado para reducir re-renderizados innecesarios, y React-Redux v5 muestra mejoras notables respecto a versiones anteriores.

Redux puede no ser tan eficiente de forma predeterminada en comparación con otras bibliotecas. Para maximizar el rendimiento de renderizado en una aplicación React, el estado debe almacenarse de forma normalizada, muchos componentes individuales deberían conectarse al store en lugar de solo unos pocos, y los componentes de lista conectados deberían pasar IDs de elementos a sus elementos hijos conectados (permitiendo que los elementos de lista busquen sus propios datos por ID). Esto minimiza la cantidad total de renderizado necesario. El uso de funciones selectoras memoizadas también es una consideración importante de rendimiento.

En cuanto a arquitectura, la evidencia anecdótica indica que Redux funciona bien para proyectos y equipos de diferentes tamaños. Actualmente cientos de empresas y miles de desarrolladores usan Redux, con varios cientos de miles de instalaciones mensuales desde NPM. Un desarrollador reportó:

a escala, tenemos ~500 tipos de acciones, ~400 casos de reducers, ~150 componentes, 5 middlewares, ~200 acciones, ~2300 tests

Más información

Documentación

Artículos

Debates

¿No será lento llamar a "todos mis reductores" para cada acción?

Es importante señalar que un almacén de Redux realmente solo tiene una única función reductora. El almacén pasa el estado actual y la acción despachada a esa única función reductora, permitiendo que maneje las cosas adecuadamente.

Obviamente, intentar manejar todas las acciones posibles en una sola función no escala bien en términos de tamaño de función y legibilidad. Por eso tiene sentido dividir el trabajo real en funciones separadas que puedan ser llamadas por el reductor principal. El patrón común sugerido es tener funciones sub-reductoras separadas responsables de actualizar segmentos específicos del estado. El combineReducers() incluido en Redux es una de las formas posibles de lograrlo. También se recomienda mantener el estado del almacén lo más plano y normalizado posible. En última instancia, tú decides cómo organizar la lógica de tus reductores.

Sin embargo, incluso con muchos reductores compuestos y estados profundamente anidados, la velocidad del reductor rara vez es un problema. Los motores JavaScript pueden ejecutar un enorme número de llamadas a funciones por segundo, y la mayoría de tus reductores probablemente solo usan una declaración switch y devuelven el estado existente por defecto para la mayoría de las acciones.

Si realmente te preocupa el rendimiento de los reductores, puedes usar utilidades como redux-ignore o reduxr-scoped-reducer para asegurar que solo ciertos reductores escuchen acciones específicas. También puedes usar redux-log-slow-reducers para realizar pruebas de rendimiento.

Más información

Debates

¿Debo clonar profundamente mi estado en un reductor? ¿No será lento copiar mi estado?

Actualizar el estado de forma inmutable generalmente implica hacer copias superficiales, no profundas. Las copias superficiales son mucho más rápidas porque copian menos objetos y campos, reduciéndose esencialmente a mover algunos punteros.

Además, clonar profundamente el estado crea nuevas referencias para cada campo. Como la función connect de React-Redux depende de comparaciones de referencia para detectar cambios, esto forzaría re-renderizados innecesarios en componentes UI incluso cuando los datos no han cambiado significativamente.

Sin embargo, necesitas crear un objeto copiado y actualizado para cada nivel de anidamiento afectado. Aunque esto no debería ser especialmente costoso, es otra buena razón para mantener tu estado normalizado y poco profundo siempre que sea posible.

Error común sobre Redux: crees que debes clonar el estado en profundidad. Realidad: si algo interno no cambia, ¡mantén su referencia igual!

Más información

Documentación

Debates

¿Cómo puedo reducir el número de eventos de actualización del almacén?

Redux notifica a los suscriptores después de cada acción despachada correctamente (es decir, cuando una acción llega al almacén y es procesada por los reductores). En algunos casos, puede ser útil reducir el número de veces que se llama a los suscriptores, especialmente cuando un creador de acciones despacha múltiples acciones distintas seguidas.

Existen varios complementos que añaden capacidades de procesamiento por lotes de diferentes formas, como: redux-batched-actions (un reductor de orden superior que permite despachar varias acciones como si fueran una y "desempaquetarlas" en el reductor), redux-batched-subscribe (un potenciador del almacén que permite agrupar llamadas a suscriptores para múltiples despachos), o redux-batch (un potenciador del almacén que maneja el despacho de un array de acciones con una sola notificación a los suscriptores).

Específicamente para React-Redux, a partir de React-Redux v7 está disponible una nueva API pública batch para ayudar a minimizar el número de rerenderizados de React al despachar acciones fuera de los controladores de eventos de React. Envuelve la API unstable_batchedUpdate() de React, permitiendo que cualquier actualización de React en un ciclo del bucle de eventos se agrupe en un único pase de renderizado. React ya usa esto internamente para sus propios callbacks de controladores de eventos. Esta API forma parte de los paquetes de renderizado como ReactDOM y React Native, no del núcleo de React en sí.

Dado que React-Redux necesita funcionar tanto en entornos ReactDOM como React Native, nos hemos encargado de importar esta API desde el renderizador correcto en tiempo de compilación para nuestro propio uso. Además, ahora reexportamos esta función públicamente nosotros mismos, renombrada como batch(). Puedes usarla para asegurarte de que múltiples acciones despachadas fuera de React resulten en una única actualización de renderizado, así:

import { batch } from 'react-redux'

function myThunk() {
return (dispatch, getState) => {
// should only result in one combined re-render, not two
batch(() => {
dispatch(increment())
dispatch(increment())
})
}
}

Más información

Debates

Bibliotecas

¿Provocará tener "un único árbol de estado" problemas de memoria? ¿Ocupará memoria enviar muchas acciones?

Primero, en términos de uso de memoria en bruto, Redux no es diferente de cualquier otra biblioteca de JavaScript. La única diferencia es que todas las referencias a objetos están anidadas en un único árbol, en lugar de guardarse en varias instancias de modelos independientes como en Backbone. Segundo, una aplicación típica de Redux probablemente consuma menos memoria que una aplicación equivalente en Backbone porque Redux fomenta el uso de objetos y arrays de JavaScript simples en lugar de crear instancias de Models y Collections. Finalmente, Redux solo mantiene una referencia al árbol de estado actual en cada momento. Los objetos que ya no estén referenciados en ese árbol serán recolectados por el recolector de basura, como es habitual.

Redux no almacena por sí mismo un historial de acciones. Sin embargo, las Redux DevTools sí guardan acciones para poder reproducirlas, pero generalmente solo están activadas durante el desarrollo y no se usan en producción.

Más información

Documentación

Debates

¿Provocarán problemas de memoria almacenar en caché datos remotos?

La cantidad de memoria disponible para aplicaciones JavaScript en un navegador es limitada. El almacenamiento en caché causará problemas de rendimiento cuando el tamaño de la caché se aproxime a la memoria disponible. Esto suele ocurrir cuando los datos almacenados son excepcionalmente grandes o las sesiones son muy largas. Si bien es bueno conocer estos posibles problemas, esta conciencia no debería disuadirte de almacenar en caché cantidades razonables de datos de manera eficiente.

Estos son algunos enfoques para almacenar datos remotos en caché de forma eficiente:

Primero, almacena solo los datos que el usuario necesita. Si tu aplicación muestra una lista paginada de registros, no es necesario guardar en caché toda la colección. En su lugar, almacena lo que es visible para el usuario y añade más datos cuando el usuario tenga (o vaya a tener) una necesidad inmediata de ellos.

Segundo, almacena versiones resumidas de los registros cuando sea posible. A veces un registro incluye datos irrelevantes para el usuario. Si la aplicación no depende de esta información, puede omitirse en la caché.

Tercero, almacena solo una copia única de cada registro. Esto es crucial cuando los registros contienen copias de otros registros. Guarda una copia única para cada registro y reemplaza las copias anidadas por referencias. Esto se llama normalización. La normalización es el enfoque preferido para almacenar datos relacionales por varias razones, incluido el consumo eficiente de memoria.

Más información

Debates