Si las tiendas mantienen su propio estado y tienen la capacidad de llamar a la red y a los servicios de almacenamiento de datos al hacerlo ... en cuyo caso las acciones son solo mensajes tontos,
-O-
... ¿las tiendas deben ser tontas receptoras de datos inmutables de las acciones (y las acciones son las que obtienen / envían datos entre fuentes externas? La tienda en este caso actuaría como modelos de vista y podría agregar / filtrar sus datos antes de establecer su propia base de estado en los datos inmutables que fueron alimentados por la acción.
Me parece que debería ser uno u otro (en lugar de una mezcla de ambos). Si es así, ¿por qué uno es preferido / recomendado sobre el otro?
reactjs
reactjs-flux
plaxdan
fuente
fuente
Respuestas:
He visto que el patrón de flujo se implementa en ambos sentidos, y después de haberlo hecho yo mismo (inicialmente siguiendo el enfoque anterior), creo que las tiendas deberían ser destinatarios tontos de datos de las acciones, y que el procesamiento asincrónico de las escrituras debería vivir en el creadores de acción. (Las lecturas asíncronas se pueden manejar de manera diferente ). En mi experiencia, esto tiene algunos beneficios, en orden de importancia:
Sus tiendas se vuelven completamente sincrónicas. Esto hace que la lógica de su tienda sea mucho más fácil de seguir y muy fácil de probar: simplemente cree una instancia de una tienda con un estado determinado, envíele una acción y verifique si el estado cambió como se esperaba. Además, uno de los conceptos centrales de flujo es evitar los despachos en cascada y evitar múltiples despachos a la vez; Esto es muy difícil de hacer cuando sus tiendas realizan un procesamiento asincrónico.
Todos los despachos de acción suceden de los creadores de la acción. Si maneja operaciones asincrónicas en sus tiendas y desea mantener sincronizados los manejadores de acciones de sus tiendas (y debe hacerlo para obtener las garantías de despacho único de flujo), sus tiendas necesitarán disparar acciones de ÉXITO y FALLO adicionales en respuesta a asincrónicas Procesando. En cambio, poner estos despachos en los creadores de acciones ayuda a separar los trabajos de los creadores de acciones y las tiendas; Además, no tiene que buscar en la lógica de su tienda para averiguar desde dónde se envían las acciones. Una acción asincrónica típica en este caso podría verse más o menos así (cambie la sintaxis de las
dispatch
llamadas según el sabor del flujo que esté usando):La lógica que de otro modo podría duplicarse en varias acciones debería extraerse en un módulo separado; en este ejemplo, ese módulo sería
SomeDataAccessLayer
, que se encarga de hacer la solicitud real de Ajax.Necesitas menos creadores de acción. Esto es menos importante, pero es bueno tenerlo. Como se menciona en el n. ° 2, si sus tiendas tienen manejo de despacho de acciones síncronas (y deberían hacerlo), necesitará disparar acciones adicionales para manejar los resultados de las operaciones asíncronas. Hacer los despachos en los creadores de acciones significa que un solo creador de acciones puede despachar los tres tipos de acciones manejando el resultado del acceso asíncrono a los datos.
fuente
"SOME_ACTION"
), usar una API para hacer una solicitud (SomeDataAccessLayer.doSomething(userId)
) que devuelve una promesa, y en las dos.then
funciones, despachar acciones adicionales. El estado de solicitud puede (más o menos) correlacionarse con el estado de almacenamiento si la aplicación necesita saber sobre el estado del estado. Cómo este mapa depende de la aplicación (por ejemplo, tal vez cada comentario tiene un estado de error individual, a la Facebook, o tal vez hay un componente de error global)Tuiteé esta pregunta a los desarrolladores en Facebook y la respuesta que recibí de Bill Fisher fue:
fuente
a call from store works better when action triggers from non-human driver
?Las tiendas deben hacer todo, incluida la obtención de datos y la señalización a los componentes de que los datos de la tienda se han actualizado. ¿Por qué? Porque las acciones pueden ser ligeras, desechables y reemplazables sin influir en el comportamiento importante. Todos los comportamientos y funcionalidades importantes suceden en la tienda. Esto también evita la duplicación de comportamientos que de otro modo se copiarían en dos acciones muy similares pero diferentes. Las tiendas son su única fuente de (manejo de) la verdad.
En cada implementación de Flux que he visto, las acciones son básicamente cadenas de eventos convertidas en objetos, como tradicionalmente tendría un evento llamado "ancla: cliqueado", pero en Flux se definiría como AnchorActions.Clicked. Incluso son tan "tontos" que la mayoría de las implementaciones tienen objetos Dispatcher separados para enviar los eventos a las tiendas que están escuchando.
Personalmente, me gusta la implementación de Reflux de Flux donde no hay objetos Dispatcher separados y los objetos Action hacen el despacho ellos mismos.
editar: Flux de Facebook en realidad busca a los "creadores de acciones" para que usen acciones inteligentes. También preparan la carga útil utilizando las tiendas:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (líneas 27 y 28)
La devolución de llamada al finalizar desencadenaría una nueva acción esta vez con los datos obtenidos como carga útil:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51
Así que supongo que esa es la mejor solución.
fuente
Proporcionaré un argumento a favor de las acciones "tontas".
Al asignar la responsabilidad de recopilar datos de vistas en sus Acciones, las une a los requisitos de datos de sus vistas.
Por el contrario, las Acciones genéricas, que describen de manera declarativa la intención del usuario, o alguna transición de estado en su aplicación, permiten que cualquier Tienda que responda a esa Acción transforme la intención, en un estado diseñado específicamente para las vistas suscritas.
Esto se presta a tiendas más numerosas, pero más pequeñas y más especializadas. Defiendo este estilo porque
El propósito de una tienda es proporcionar datos a las vistas. El nombre "Acción" me sugiere que su propósito es describir un cambio en mi Aplicación.
Suponga que tiene que agregar un widget a una vista de Panel existente, que muestra algunos datos agregados nuevos y sofisticados que su equipo de back-end acaba de implementar.
Con las acciones "inteligentes", es posible que deba cambiar su acción "Actualizar panel" para consumir la nueva API. Sin embargo, "Actualizar el tablero" en sentido abstracto no ha cambiado. Los requisitos de datos de sus vistas es lo que ha cambiado.
Con las acciones "tontas", puede agregar una nueva Tienda para que el nuevo widget la consuma y configurarla de modo que cuando reciba el tipo de Acción "actualizar panel", envíe una solicitud de los nuevos datos y la exponga a el nuevo widget una vez que esté listo. Tiene sentido para mí que cuando la capa de vista necesita más o diferentes datos, las cosas que cambio son las fuentes de esos datos: las tiendas.
fuente
La demostración de enrutador-flujo-reacción de Gaeron tiene una buena variación de utilidad del enfoque 'correcto'.
Un ActionCreator genera una promesa desde un servicio API externo y luego pasa la promesa y tres constantes de acción a una
dispatchAsync
función en un proxy / Dispatcher extendido.dispatchAsync
siempre enviará la primera acción, por ejemplo, 'GET_EXTERNAL_DATA' y una vez que la promesa regrese, enviará 'GET_EXTERNAL_DATA_SUCCESS' o 'GET_EXTERNAL_DATA_ERROR'.fuente
Si desea que un día tenga un entorno de desarrollo comparable al que ve en el famoso video de Bret Victor Inventing on Principle , debería usar tiendas tontas que son solo una proyección de acciones / eventos dentro de una estructura de datos, sin ningún efecto secundario. También sería útil que sus tiendas fueran realmente miembros de la misma estructura de datos inmutable global, como en Redux .
Más explicaciones aquí: https://stackoverflow.com/a/31388262/82609
fuente