tutorial react example reactjs reactjs-flux

reactjs - react - ¿Deben las tiendas de flujo o acciones(o ambas) tocar servicios externos?



react flux github (6)

Si las tiendas mantienen su propio estado y tienen la capacidad de llamar a la red y a los servicios de almacenamiento de datos para hacerlo ... en cuyo caso las acciones son solo mensajes pasadores tontos,

-O-

... ¿las tiendas deben ser tontas receptoras de datos inmutables de las acciones (y las acciones deben ser 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?


Flux flux-react-router-demo 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 función dispatchAsync 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á ya sea ''GET_EXTERNAL_DATA_SUCCESS'' o ''GET_EXTERNAL_DATA_ERROR''.


He visto que el patrón de flujo se implementó en ambos sentidos, y después de haberlo hecho yo mismo (inicialmente siguiendo el enfoque anterior), creo que las tiendas deberían ser tontas receptoras 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:

  1. 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: solo cree una instancia 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.

  2. 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 tratamiento. 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 de 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 llamadas de dispatch según el sabor del flujo que esté usando):

    someActionCreator: function(userId) { // Dispatch an action now so that stores that want // to optimistically update their state can do so. dispatch("SOME_ACTION", {userId: userId}); // This example uses promises, but you can use Node-style // callbacks or whatever you want for error handling. SomeDataAccessLayer.doSomething(userId) .then(function(newData) { // Stores that optimistically updated may not do anything // with a "SUCCESS" action, but you might e.g. stop showing // a loading indicator, etc. dispatch("SOME_ACTION_SUCCESS", {userId: userId, newData: newData}); }, function(error) { // Stores can roll back by watching for the error case. dispatch("SOME_ACTION_FAIL", {userId: userId, error: error}); }); }

    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.

  3. 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), deberá activar 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.


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 declarativamente 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

  • esto le brinda más flexibilidad en cómo las vistas consumen los datos de la Tienda
  • Las tiendas "inteligentes", especializadas para las vistas que las consumen, serán más pequeñas y menos acopladas para aplicaciones complejas que las acciones "inteligentes", de las cuales dependen potencialmente muchas vistas.

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 "refrescar-tablero", envíe una solicitud de los nuevos datos y la exponga a el nuevo widget una vez que esté listo. Para mí tiene sentido que cuando la capa de vista necesita más o diferentes datos, las cosas que cambio son las fuentes de esos datos: las tiendas.


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://.com/a/31388262/82609


Tuiteé esta pregunta a los desarrolladores en Facebook y la respuesta que recibí de Bill Fisher fue:

Al responder a la interacción de un usuario con la interfaz de usuario, haría la llamada asincrónica en los métodos de creación de acciones.

Pero cuando tiene un ticker u otro controlador no humano, una llamada de la tienda funciona mejor.

Lo importante es crear una acción en la devolución de llamada de error / éxito para que los datos siempre se originen con acciones


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 "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.