Introducción a Redux-Logic

Este artículo pasará por una descripción general de alto nivel de Redux-Logic. Veremos qué es, por qué es necesario, en qué se diferencia de otros middleware de Redux y por qué creo que es la mejor opción. Luego veremos un ejemplo de una aplicación meteorológica simple para demostrar cómo se ponen en práctica los conceptos básicos.

Este artículo asume que tiene un buen conocimiento de React y Redux.

Un repaso rápido sobre Redux

Redux es un contenedor de estado para aplicaciones JavaScript y se usa comúnmente con React. Proporciona un lugar central para almacenar datos que se utilizan en su aplicación. Redux también proporciona un marco para realizar mutaciones de estado predecibles . El uso de Redux facilita la escritura, comprensión, depuración y escalado de aplicaciones dinámicas y basadas en datos.

En Redux, los componentes llaman a los creadores de acciones que envían acciones . Las acciones son (¡generalmente!) Pequeños objetos simples que expresan una intención o una instrucción. Las acciones también pueden contener "cargas útiles" (es decir, datos).

El estado de la aplicación está gestionado por reductores . ¡Suenan más complicados de lo que son! Las acciones son manejadas por un reductor raíz que luego pasa la acción y la carga útil a un reductor en particular. Este reductor tomará una copia del estado de la aplicación, mutará la copia (de acuerdo con la acción y su carga útil) y luego actualizará el estado en la tienda de aplicaciones .

¿Por qué la necesidad de Redux Logic?

De forma predeterminada, todas las acciones en Redux se envían sincrónicamente. Esto presenta un desafío para cualquier aplicación que necesite admitir un comportamiento asincrónico, como obtener datos de una API ... ¡prácticamente cualquier aplicación!

Para manejar el comportamiento asíncrono usando Redux, necesitamos algún tipo de middleware que realice algún procesamiento entre el momento en que se envía la acción y cuando la acción llega a los reductores. Existen varias bibliotecas populares para proporcionar esta funcionalidad.

Después de explorar las distintas opciones, he estado usando Redux-Logic en una variedad de proyectos por un tiempo y lo he encontrado genial.

Ciclo de vida de Redux-Logic

Redux-Logic proporciona middleware que realiza algún procesamiento entre el momento en que se envía una acción desde un componente y cuando la acción alcanza un reductor.

Usamos la biblioteca redux-logic para crear 'Logic'. Estas son esencialmente funciones que particulares de intercepción de objetos lisos acciones, realizan el procesamiento asíncrono y luego despachan otro objec llanura acción t. Las funciones lógicas son realmente declarativas y flexibles, como veremos.

Una cosa importante a tener en cuenta aquí es que todas las acciones con las que trabaja Redux-Logic son objetos simples . La acción que envía el componente de IU y la acción que luego envía Logic siempre será un objeto simple (a diferencia de, por ejemplo, una función). Revisaremos esto a continuación cuando comparemos diferentes opciones de middleware.

Bajo el capó, Redux-Logic utiliza programación reactiva y observables. Lea mas sobre eso, aqui.

Flujo de datos

A continuación, a modo de comparación, hay un diagrama que creé que muestra los puntos importantes en el ciclo de vida de un proceso redux sincrónico. No se incluye middleware (¡porque no se necesita ninguno!).

Ahora aquí hay un diagrama que muestra las partes importantes de un proyecto que usa la biblioteca redux-logic para manejar acciones asincrónicas. Será útil consultarlo más adelante junto con el ejemplo siguiente.

Puede ver cómo funciona el middleware entre el momento en que se envía una acción y cuando es manejada por un reductor.

Principales diferencias con otras soluciones

Redux-Thunk es una opción popular para el middleware de Redux que también le permite admitir el comportamiento asincrónico. Para manejar el comportamiento asincrónico usando Redux-Thunk, sus creadores de acciones deben devolver funciones en lugar de devolver objetos simples con Redux-Logic. Creo que enviar objetos simples con Redux-Logic hace que su código sea mucho más fácil de escribir y mucho más fácil de entender.

Además, creo que el enfoque de 'objeto simple' para manejar el comportamiento asincrónico encaja de manera más natural junto con el resto de la arquitectura (sincrónica) de Redux, lo que hace que este middleware se adapte más orgánicamente a Redux.

Otro middleware popular de Redux es Redux-Saga . Encontré la curva de aprendizaje de entender las sagas (una característica relativamente nueva de ES6) bastante empinada cuando miré esta opción. Esto se agravaría si quisiera introducir esta biblioteca en una aplicación administrada por un equipo con varias personas. Además, creo que si no están bien administrados, las sagas pueden crear un código de aspecto complicado en comparación con la lógica que crea con redux-logic. Esto puede afectar la velocidad de desarrollo y la capacidad de mantenimiento del código.

Resumen del ejemplo

A continuación se muestran fragmentos simples de una aplicación React simple que puede obtener las condiciones climáticas actuales en una ciudad y presentárselas al usuario. El ejemplo utiliza Redux-Logic para admitir el comportamiento asincrónico para obtener datos mediante una API OpenWeatherMap gratuita.

A modo de comparación, he incluido un proceso de Redux sincrónico que muestra el número de solicitudes que ha realizado un usuario.

Aquí está el código fuente.

Configuración del entorno de desarrollo

Estos son los comandos que ejecuté para comenzar a crear mi aplicación:

npx create-react-app appnpm install --save reduxnpm install --save react-reduxnpm install --save redux-logicnpm install --save axios

Y para ver la aplicación:

npm start

Feliz de poder ver la página de inicio predeterminada de Create React App en localhost: 3000 , ¡luego comencé a escribir un código!

A continuación, se muestran fragmentos de código que muestran los puntos importantes sobre la integración de Redux-Logic en el proyecto.

Añadiendo middleware a nuestra tienda Redux

En appStore.js , si no estuviéramos usando ningún middleware, normalmente solo proporcionaríamos nuestro reductor de raíz al método createStore. Aquí es donde enlazamos nuestro middleware Redux-Logic con el resto de nuestra aplicación.

Especificamos que queremos usar axios como nuestro cliente para realizar solicitudes HTTP.

Luego usamos un método de redux-logic para crear nuestro middleware y finalmente lo agregamos como parámetro al método createStore. Esto significa que nuestro código Redux podrá acceder a nuestro middleware. ¡Excelente!

Despacho de acciones asincrónicas

Con Redux-Logic, las acciones que desencadenan un comportamiento asincrónico se distribuyen de la misma manera que las acciones que desencadenan actualizaciones de estado sincrónicas. ¡No hay nada diferente!

Para completar, puede ver a continuación que cuando un usuario hace clic en un botón, llamamos a un creador de acciones que se ha pasado a nuestro componente como accesorios.

Interceptar acciones asincrónicas

Aquí es donde vemos por primera vez la aparición del middleware redux-logic entrando en juego. Estamos usando la biblioteca redux-logic para crear alguna 'Lógica' que interceptará acciones específicas.

En nuestras propiedades lógicas le decimos a redux-logic qué acción queremos que intercepte. Especificamos que queremos que redux-logic solo proporcione datos de la última acción de este tipo que envió el componente. En nuestro ejemplo, este comportamiento declarativo es útil si las personas siguen haciendo clic en un botón, ya que obtendrán el valor de la última acción que enviaron, ¡no necesariamente la última promesa de regresar!

A continuación, especificamos que cuando el proceso asincrónico regresa, despachamos inmediatamente una de dos acciones. Si la promesa se devolvió correctamente, devolvemos una acción GET_WEATHER_FOR_CITY_SUCCESSFUL . ¡Esto es lo que queremos!

Alternativamente, si la promesa devuelta fue rechazada, enviamos GET_WEATHER_FOR_CITY_FAILURE .

Aquí es donde realmente brilla la lógica redux . Está claro cuál es la intención del código lógico, y lo que se emite son objetos simples que son fáciles de leer e interpretar. Encuentro esto realmente fácil de leer, comprender y depurar.

En la parte inferior dejamos claro qué queremos que haga nuestro proceso asincrónico. Queremos devolver el valor de una promesa. Observe cómo pasamos la carga útil que vino con nuestra acción a la URL.

Procesamiento de acciones asincrónicas

Puede ver en el reductor weatherDataHandling.js que las acciones enviadas desde nuestra lógica se tratan como acciones de objetos simples. Los reductores mutan el estado de la misma forma que con las acciones sincrónicas . Entonces, la captura de pantalla a continuación es lo que esperaría de trabajar con Redux antes. ¡Súper!

Resumen

Redux es un contenedor de estado predecible popular para aplicaciones JavaScript. De forma predeterminada, todas las acciones de Redux solo admiten el comportamiento síncrono, y necesitará algún tipo de solución de middleware para el comportamiento asincrónico.

Redux-Logic proporciona un middleware claro y potente que le permite utilizar acciones asincrónicas en su aplicación Redux. Agrega su middleware a su tienda Redux para permitir que su aplicación use Redux-Logic. Utiliza la biblioteca redux-logic para crear Logic, que intercepta acciones particulares y envía acciones adicionales después de que se completa algún procesamiento asincrónico (como obtener datos de una API).

Todas las acciones involucradas son acciones de objetos simples . Creo que esto facilita la escritura y la comprensión en comparación con otras soluciones. Además, redux-logic se siente como un ajuste más orgánico con las otras partes de la arquitectura Redux.

Gracias por leer, doy la bienvenida a cualquier comentario o pregunta a continuación.