Ir al contenido principal

Decisiones de diseño

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 →

FAQ de Redux: Decisiones de diseño

¿Por qué Redux no pasa el estado y la acción a los suscriptores?

Los suscriptores están diseñados para responder al valor del estado en sí, no a la acción. Las actualizaciones del estado se procesan de forma síncrona, pero las notificaciones a los suscriptores pueden agruparse o retrasarse (batched/debounced), lo que significa que los suscriptores no siempre reciben notificación con cada acción. Esta es una optimización de rendimiento común para evitar re-renderizaciones repetidas.

Es posible agrupar o retrasar notificaciones mediante el uso de enhancers que sobrescriben store.dispatch para modificar cómo se notifica a los suscriptores. Además, existen bibliotecas que modifican Redux para procesar acciones en lotes y así optimizar el rendimiento evitando re-renderizaciones repetidas:

  • redux-batch permite pasar un array de acciones a store.dispatch() con una sola notificación,

  • redux-batched-subscribe permite agrupar notificaciones de suscripción resultantes de despachos.

La garantía que ofrece Redux es que eventualmente llamará a todos los suscriptores con el estado más reciente disponible, no que siempre llamará a cada suscriptor por cada acción. El estado del store está disponible en el suscriptor simplemente llamando a store.getState(). No es posible hacer que la acción esté disponible para los suscriptores sin romper el posible agrupamiento de acciones.

Un caso de uso potencial (no soportado) para usar la acción dentro de un suscriptor sería asegurar que un componente solo se re-renderice tras ciertos tipos de acciones. En su lugar, la re-renderización debe controlarse mediante:

  1. el método del ciclo de vida shouldComponentUpdate

  2. la comprobación de igualdad del DOM virtual (vDOMEq)

  3. React.PureComponent

  4. Usando React-Redux: emplea mapStateToProps para suscribir componentes solo a las partes del store que necesitan.

Información adicional

Artículos

Debates

¿Por qué Redux no admite clases para acciones y reductores?

El patrón de usar funciones (creadores de acciones) para devolver objetos de acción puede parecer contraintuitivo a programadores con experiencia en POO, que verían aquí un caso claro para usar Clases e instancias. No se admiten instancias de clase para acciones y reductores porque complican la serialización y deserialización. Métodos como JSON.parse(string) devolverían objetos simples de JavaScript, no instancias de clase.

Como se explica en las FAQ del Store, si aceptas que características como persistencia o time-travel debugging no funcionen correctamente, puedes incluir elementos no serializables en tu store de Redux.

La serialización permite al navegador almacenar todas las acciones despachadas y estados previos del store con mucho menos memoria. El rebobinado y "hot reloading" son esenciales para la experiencia de desarrollo con Redux y el funcionamiento de Redux DevTools. Esto también permite almacenar acciones deserializadas en el servidor y reserializarlas en el navegador para renderizado en servidor con Redux.

Información adicional

Artículos

Debates

¿Por qué la firma del middleware usa currificación?

Los middlewares de Redux se escriben usando una estructura de función triplemente anidada como const middleware = storeAPI => next => action => {}, en lugar de una única función como const middleware = (storeAPI, next, action) => {}. Existen varias razones para esto.

Una es que las funciones "currificadas" son una técnica estándar de programación funcional, y Redux fue diseñado explícitamente para usar principios de programación funcional. Otra es que el currificado crea clausuras donde puedes declarar variables que existen durante toda la vida útil del middleware (equivalente funcional a las variables de instancia en clases). Finalmente, fue el enfoque elegido en el diseño inicial de Redux.

La firma currificada para middlewares ha sido considerada innecesaria por algunos, ya que tanto store como next están disponibles al ejecutar applyMiddleware. Se determinó que no valía la pena introducir cambios disruptivos, existiendo cientos de middlewares en el ecosistema Redux que dependen de la definición actual.

Información adicional

Debates

¿Por qué applyMiddleware usa una clausura para dispatch?

applyMiddleware toma el dispatch existente del store y lo encapsula en una clausura para crear la cadena inicial de middlewares que han sido invocados con un objeto que expone las funciones getState y dispatch, lo que permite que los middlewares que dependen de dispatch durante la inicialización puedan ejecutarse.

Información adicional

Debates

  • ¿Por qué applyMiddleware usa una clausura para dispatch?

¿Por qué combineReducers no incluye un tercer argumento con el estado completo al llamar a cada reducer?

combineReducers tiene una filosofía clara: fomentar la división de lógica por dominios. Como se explica en Más allá de combineReducers, combineReducers está deliberadamente limitado para manejar un caso común: actualizar un árbol de estado plano delegando cada porción a un reducer específico.

No es obvio qué debería ser un tercer argumento para cada reducer: ¿el árbol completo? ¿una función callback? ¿otra parte del estado? Si combineReducers no cubre tu caso, considera bibliotecas alternativas como combineSectionReducers o reduceReducers para manejar reducers anidados o que necesiten acceso al estado global.

Si ninguna de las utilidades publicadas resuelve tu caso de uso, siempre puedes escribir una función personalizada que haga exactamente lo que necesitas.

Más información

Artículos

Debates

¿Por qué mapDispatchToProps no permite usar valores devueltos por getState() o mapStateToProps()?

Existen solicitudes para usar tanto el state completo como el valor devuelto por mapState dentro de mapDispatch, permitiendo que las funciones declaradas en mapDispatch accedan a los últimos valores del store.

Este enfoque no está soportado en mapDispatch porque implicaría ejecutar mapDispatch en cada actualización del store. Esto generaría recreación constante de funciones con cada cambio de estado, añadiendo una gran sobrecarga de rendimiento.

La forma preferida de manejar este caso—necesidad de modificar props basándose en el estado actual y funciones de mapDispatchToProps—es trabajar con mergeProps, el tercer argumento de la función connect. Si se especifica, recibe los resultados de mapStateToProps(), mapDispatchToProps() y las props del componente contenedor. El objeto simple devuelto por mergeProps se pasará como props al componente envuelto.

Más información

Debates