Redux: varias tiendas, ¿por qué no?

221

Como nota: he leído los documentos de Redux (Baobab, también), y he hecho una buena cantidad de Google y pruebas.

¿Por qué se sugiere que una aplicación Redux tenga solo una tienda?

Entiendo las ventajas y desventajas de una configuración de tienda única frente a una configuración de tienda múltiple ( hay muchas preguntas y respuestas sobre SO sobre este tema ).

En mi opinión, esta decisión arquitectónica pertenece a los desarrolladores de aplicaciones en función de las necesidades de sus proyectos. Entonces, ¿por qué se recomienda tanto para Redux, casi hasta el punto de sonar obligatorio ( aunque nada nos impide hacer varias tiendas )?

EDITAR: comentarios después de convertir a una sola tienda

Después de unos meses trabajando con redux en lo que muchos considerarían un SPA complejo, puedo decir que la estructura de una sola tienda ha sido un placer trabajar con ella.

Algunos puntos que podrían ayudar a otros a entender por qué una sola tienda frente a muchas tiendas es una cuestión discutible en muchos, muchos casos de uso:

  • es confiable : utilizamos selectores para explorar el estado de la aplicación y obtener información relevante para el contexto. Sabemos que todos los datos necesarios están en una sola tienda. Evita todos los cuestionamientos sobre dónde podrían estar los problemas estatales.
  • es rápido : nuestra tienda actualmente tiene cerca de 100 reductores, si no más. Incluso en ese caso, solo un puñado de reductores procesa datos en cualquier envío dado, los otros simplemente devuelven el estado anterior. El argumento de que una tienda enorme / compleja ( nbr de reductores ) es lenta es bastante discutible. Al menos no hemos visto ningún problema de rendimiento a partir de ahí.
  • depuración amigable : si bien este es un argumento muy convincente para usar redux como un todo, también se aplica a una tienda individual frente a una tienda múltiple. Al crear una aplicación, es probable que tenga errores de estado en el proceso ( errores del programador ), es normal. El PITA es cuando esos errores tardan horas en depurarse. Gracias a la tienda única ( y redux-logger ) nunca hemos dedicado más de unos minutos a un problema de estado determinado.

algunos consejos

El verdadero desafío al construir su tienda redux es decidir cómo estructurarla . En primer lugar, porque cambiar la estructura en el futuro es solo un gran dolor. En segundo lugar, porque determina en gran medida cómo usará y consultará los datos de su aplicación para cualquier proceso. Hay muchas sugerencias sobre cómo estructurar una tienda. En nuestro caso, encontramos que lo siguiente es ideal:

{
  apis: {     // data from various services
    api1: {},
    api2: {},
    ...
  }, 
  components: {} // UI state data for each widget, component, you name it 
  session: {} // session-specific information
}

Esperemos que este comentario ayude a otros.

EDIT 2 - herramientas útiles de la tienda

Para aquellos de ustedes que se han estado preguntando cómo administrar "fácilmente" una sola tienda , lo que puede volverse complejo rápidamente. Hay herramientas que ayudan a aislar las dependencias estructurales / lógica de su tienda.

Hay Normalizr que normaliza sus datos en función de un esquema. Luego proporciona una interfaz para trabajar con sus datos y buscar otras partes de sus datos id, de forma muy similar a un diccionario.

Sin conocer Normalizr en ese momento, construí algo en la misma línea. relational-json toma un esquema y devuelve una interfaz basada en tablas ( un poco como una base de datos ). La ventaja de relational-json es que su estructura de datos hace referencia dinámica a otras partes de sus datos ( esencialmente, puede atravesar sus datos en cualquier dirección, al igual que los objetos JS normales ). No es tan maduro como Normalizr, pero lo he estado usando con éxito en producción durante algunos meses.

Sebastien Daniel
fuente
44
Me gusta su enfoque para la estructura de la tienda que está utilizando; sin embargo, ¿cómo maneja la asignación de cambios de estado de la API a los cambios de estado de sus componentes? Digamos que recibo datos específicos del dominio de mi API, ¿cómo se traduce esto en una estructura de datos genérica que se encontraría en mis componentes?
Diniden
La forma en que sus componentes mapean / usan los datos de la tienda depende de usted, realmente. Aunque creo que no entiendo completamente su pregunta, ¿podría elaborar o iniciar una sesión de chat?
Sebastien Daniel
2
Supongo que la pregunta sería: ¿sus componentes procesan alguno desde el estado de la API, o solo procesan lo que se pone en el estado de los componentes? Sospecharía que si solo lograra renderizar desde el estado del componente, entonces ha encontrado una excelente manera de hacer que sus componentes y contenedores sean altamente reutilizables incluso en presencia de datos específicos del dominio. Si sus componentes se procesan parcialmente desde el estado API y el estado del componente, entonces supongo que está utilizando Contenedores específicos de dominio para asignar los datos en apis a listas genéricas y primitivas que sus componentes entienden.
Diniden
2
Utilizo Redux junto con selectores, que son básicamente mapeadores de datos funcionalmente puros y memorizados. Cada componente "reacciona" para almacenar actualizaciones, y si un cambio es relevante para él, "selecciona" los datos y los procesa en consecuencia. Entonces, sí, los componentes SOLO se procesan según lo que les importa. Pero eso no es solo por Redux o la estructura de la tienda. Se debe a la combinación de un almacén de datos inmutable, una prueba de comparación referencial para cambios de datos y un selector puro que obtiene los datos que necesita el componente, en el formato que lo necesita.
Sebastien Daniel
Hola @SebastienDaniel, ¿podrías mostrar un ejemplo de cómo estás implementando la verificación que cada componente hace para saber si el cambio en la actualización de la tienda es relevante para él? Es decir, si está utilizando algún tipo de patrón genérico ... o si en cada caso específico está verificando si los datos específicos relacionados con los componentes han cambiado.
John Bernardsson

Respuestas:

232

Hay casos extremos en los que puede usar varias tiendas (por ejemplo, si tiene problemas de rendimiento al actualizar listas de miles de elementos que están en la pantalla al mismo tiempo muchas veces por segundo). Dicho esto, es una excepción y en la mayoría de las aplicaciones nunca necesitas más que una sola tienda.

¿Por qué enfatizamos esto en los documentos? Debido a que la mayoría de las personas que provienen de los antecedentes de Flux asumirán que múltiples tiendas es la solución para hacer que el código de actualización sea modular. Sin embargo, Redux tiene una solución diferente para esto: composición reductora.

Tener múltiples reductores que se dividen aún más en un árbol reductor es cómo mantener las actualizaciones modulares en Redux. Si no reconoce esto y va a varias tiendas sin comprender primero la composición del reductor, perderá muchos beneficios de la arquitectura de tienda única de Redux:

  • El uso de la composición reductora facilita la implementación de "actualizaciones dependientes" a la manera waitForen Flux al escribir un reductor llamando manualmente a otros reductores con información adicional y en un orden específico.

  • Con una sola tienda, es muy fácil persistir, hidratarse y leer el estado. La representación del servidor y la captación previa de datos es trivial porque solo hay un almacenamiento de datos que debe llenarse y rehidratarse en el cliente, y JSON puede describir su contenido sin preocuparse por la identificación o el nombre de la tienda.

  • Una sola tienda hace posible las funciones de viaje en el tiempo de Redux DevTools. También facilita las extensiones de comunidad como redux-undo o redux-optimist porque operan en el nivel reductor. Tales "potenciadores reductores" no pueden escribirse para tiendas.

  • Una sola tienda garantiza que las suscripciones se invoquen solo después de que se haya procesado el envío. Es decir, cuando se notifica a los oyentes, el estado se ha actualizado completamente. Con muchas tiendas, no existen tales garantías. Esta es una de las razones por las que Flux necesita la waitFormuleta. Con una sola tienda, este no es un problema que ve en primer lugar.

  • Sobre todo, no es necesario tener varias tiendas en Redux (a excepción de los casos límite de rendimiento que se supone que debe perfilar primero de todos modos). Lo consideramos un punto importante en los documentos, por lo que le recomendamos que aprenda la composición reductora y otros patrones de Redux en lugar de usar Redux como si fuera Flux y perder sus beneficios.

Dan Abramov
fuente
11
Admito que no entendí toda la ventaja / necesidad de la composición reductora. Gracias a su respuesta, leí un poco más y un ejemplo (TodoMVC, nuevamente). Con un ejemplo tan pequeño, fue difícil entender la mejora real proporcionada por la composición reductora. Sin embargo, con un poco de reflexión, a gran escala la ganancia es (ahora) obvia. Gracias de nuevo, gran respuesta!
Sebastien Daniel
44
@Sebastien El ejemplo de "carrito de compras" es mejor para esto, creo.
Dan Abramov
3
Poco a poco estoy implementando redux en una aplicación tradicional (no SPA). Estoy usando tiendas multilpe para cada "todo" que convierto en una implementación de react / redux hasta que toda la aplicación pueda modificarse para usar la misma tienda.
Paul Knopf
55
@DanAbramov Curioso cuál sería su opinión en una situación en la que su "aplicación" principal ejecuta su propia tienda Redux e importa a través de npm una "aplicación" independiente que ejecuta su propia tienda Redux separada. Por ejemplo, si uno de los otros equipos de su empresa tiene algún tipo de servicio de mensajería con una interfaz de usuario que desea utilizar sin contaminar su tienda con esos datos.
natlee75
66
@ natlee75 "Algunas razones válidas para usar varias tiendas en Redux pueden incluir: [...] Aislar una aplicación Redux como componente en una aplicación más grande, en cuyo caso es posible que desee crear una tienda por instancia de componente raíz". De redux.js.org/docs/FAQ.html#store-setup-multiple-stores
Kevin
24

En algunas aplicaciones empresariales muy grandes con cientos o miles de reductores, a menudo es útil pensar en diferentes áreas de la aplicación como aplicaciones completamente separadas. En esos casos (donde realmente son múltiples aplicaciones que comparten un nombre de dominio), uso múltiples tiendas.

Por ejemplo, tiendo a tratar las siguientes áreas de funcionalidad comunes como aplicaciones separadas:

  • Administración
  • Analítica / datos frente a paneles
  • Gestión de facturación y flujos de compra
  • Equipo de cuentas empresariales / gestión de permisos

Si alguna de esas cosas es pequeña, consérvela como parte de la aplicación principal. Si crecen mucho (como lo hacen algunas herramientas de análisis y administración de cuentas empresariales), divídalos.

La mejor manera de administrar aplicaciones muy grandes es tratarlas como una composición de muchas aplicaciones más pequeñas.

Si su aplicación es inferior a ~ 50k LOC, probablemente debería ignorar este consejo y seguir el consejo de Dan.

Si su aplicación tiene más de 1 millón de LOC, probablemente deba dividir las mini aplicaciones, incluso si las mantiene en un repositorio mono.

Eric Elliott
fuente
5

Esta decisión arquitectónica pertenece a los desarrolladores de aplicaciones en función de las necesidades de sus proyectos.

Estás viviendo en tu propio mundo. Me estoy reuniendo con personas que usan redux, porque es popular, todos los días. Ni siquiera se podía imaginar cuántos proyectos se comenzaron a reducir sin tomar ninguna decisión. Odio los enfoques redux pero tuve que usarlo, porque otros desarrolladores no saben nada más. Es solo una burbuja épica inflada por Facebook.

  • No es confiable porque las partes de la tienda no están aisladas.
  • Es ineficiente porque estás clonando y atravesando hash trie. Cuando las mutaciones crecen aritméticamente, la complejidad crece geométricamente. No podría solucionarlo refactorizando ningún reductor, selector, etc. Debe dividir su trie.
  • Cuando se vuelve lento, nadie quiere dividirlo en aplicaciones separadas con tiendas separadas. Nadie quiere gastar dinero en refactorizar. La gente generalmente está convirtiendo algunos componentes inteligentes en un volcado y eso es todo. ¿Sabes qué futuro les espera a los desarrolladores de redux? Mantendrán estos infiernos.
  • No es una depuración amigable . Es difícil depurar las conexiones entre partes virtualmente aisladas de la tienda. Es muy difícil incluso analizar la cantidad de estas conexiones.

Imaginemos que tiene varias tiendas redux. Romperá el flujo de datos unidireccional. Inmediatamente se dará cuenta de cuántas conexiones entre tiendas tiene. Puedes sufrir estas conexiones, pelear con deps circulares, etc.

El almacén único inmutable con flujo unidireccional no es un elixir para todas las enfermedades. Si no desea mantener la arquitectura del proyecto, sufrirá de todos modos.

puchu
fuente
Me gustó lo que dijiste, y aquí hice una pregunta relacionada sobre esto. ¿Le importaría mirar esto cuando tenga tiempo y comparta sus opiniones? La pregunta que hice en Reddit, porque SO no fomenta tales preguntas aquí.
Arup Rakshit
3

Las tiendas múltiples pueden ser útiles en los siguientes casos de uso 1. Si tiene componentes grandes que son independientes entre sí en términos de estructura de datos, comportamiento y contexto de aplicación. Aislar estos componentes hace que sea más fácil administrar sus datos y el flujo de aplicaciones. También ayuda al desarrollo y mantenimiento independientes de sus componentes. 2. Problemas de rendimiento: no es un caso de uso típico, pero si algunos de sus componentes se actualizan con mucha frecuencia y no tienen ningún impacto en otros componentes, probablemente puede ir a diferentes tiendas.

Para todos los demás casos, es posible que no necesite tener varias tiendas. Como dice Dan, crear composiciones reductoras bien pensadas puede ser una mejor solución.

newtonflash
fuente
Su mensaje se ve como "use redux siempre excepto en algunos casos" == "no necesita arquitectura de proyecto excepto en pocos casos". Está muy cerca de la realidad, estoy feliz.
puchu
2

¿por qué no podemos usar múltiples tiendas usando redux ????

Esto no es necesario en Redux porque la separación entre dominios de datos ya se logra dividiendo un solo reductor en reductores más pequeños.


¿Puedo o debo crear varias tiendas? ¿Puedo importar mi tienda directamente y usarla en componentes yo mismo?

El patrón original de Flux describe tener múltiples "tiendas" en una aplicación, cada una con un área diferente de datos de dominio. Esto puede presentar problemas como la necesidad de tener una tienda "esperar" a que se actualice otra tienda.

Esto no es necesario en Redux porque la separación entre dominios de datos ya se logra dividiendo un solo reductor en reductores más pequeños.

Al igual que con varias otras preguntas, es posible crear múltiples tiendas Redux distintas en una página, pero el patrón previsto es tener una sola tienda. Tener una sola tienda permite usar Redux DevTools, simplifica la persistencia y la rehidratación de datos y simplifica la lógica de suscripción.

Algunas razones válidas para usar varias tiendas en Redux pueden incluir:

Resolver un problema de rendimiento causado por actualizaciones demasiado frecuentes de alguna parte del estado, cuando se confirma mediante el perfil de la aplicación. Aislar una aplicación Redux como componente en una aplicación más grande, en cuyo caso es posible que desee crear una tienda por instancia de componente raíz. Sin embargo, crear nuevas tiendas no debería ser tu primer instinto, especialmente si vienes de un fondo Flux. Pruebe primero la composición reductora, y solo use varias tiendas si no resuelve su problema.

Del mismo modo, si bien puede hacer referencia a su instancia de tienda importándola directamente, este no es un patrón recomendado en Redux. Si crea una instancia de tienda y la exporta desde un módulo, se convertirá en un singleton. Esto significa que será más difícil aislar una aplicación Redux como componente de una aplicación más grande, si es necesario, o habilitar la representación del servidor, porque en el servidor desea crear instancias de tienda separadas para cada solicitud.

documento oficial de redux

Rizo
fuente
1

Tener una tienda en Redux es realmente lo que necesitamos en muchos casos, ¡utilicé Redux y Flux y creo que Redux hace el trabajo mejor!

No olvide que la tienda está en un Objeto JavaScript, por lo tanto, si bien tiene una sola tienda, puede ampliarse y reutilizarse fácilmente, para mí, tener una tienda hace que sea mucho más fácil atravesar usando las herramientas de desarrollo de Redux y no mezclarse en grandes aplicaciones ...

Además, el concepto de una tienda es imitar la base de datos para nosotros, una fuente de verdad que puede cambiar y acceder a ella en la memoria del navegador ...

Si toda la aplicación está bien administrada, una tienda puede ser suficiente para administrar todo el estado de la aplicación ...

Alireza
fuente
3
Por lo tanto, todos deberían creer que una sola tienda hará un mejor trabajo y nadie podría explicar por qué. Me recuerda algo ...
puchu 01 de