Al trabajar con frameworks populares como React o Vue, debemos organizar un almacenamiento conveniente y gestionar el estado de la aplicación. Por ejemplo, React permite gestionar el estado de los componentes de forma inmediata mediante this.setState y this.state. Sin embargo, con el crecimiento de la aplicación viene la necesidad de comunicación entre los componentes que a menudo resulta en una funcionalidad insuficiente. Por suerte, en el mundo del front-end, hay muchas librerías listas para ayudar a simplificar esta tarea. Este artículo analiza dos de las soluciones más populares en este momento
: Redux y MobX.

Acerca de Redux y MobX

Actualmente, la biblioteca más popular para almacenar el estado de las aplicaciones es Redux, inventada en 2015 por Dan Abramov y Andrew Clark. Se basa en la arquitectura Flux y en la programación funcional. Los usuarios de Redux obtienen el apoyo de una fuerte comunidad y una rica base de código, por lo que obtener respuesta a cualquier pregunta relacionada con la biblioteca ya no es un problema.

La alternativa más extendida es MobX, inventada por Michel Weststrate en 2015. Se implementa en los principios de la programación reactiva funcional (FRP) y permite envolver los estados en objetos “observables”. Esto facilita la reacción ante cualquier cambio de estado de la aplicación.

Flujo de datos y diferencias clave

Redux:

  • Sólo tiene un almacén como única fuente de verdad. El estado se almacena en un objeto JavaScript normal. Es mejor mantener el estado normalizado y plano.
  • El estado es inmutable. Cualquier actualización del estado siempre devuelve una nueva copia del mismo.
  • Todas las actualizaciones del estado se hacen despachando una acción específica.
  • Los reductores responden a las acciones y devuelven una nueva copia del estado si se ha actualizado.

MobX:

  • Puede tener múltiples almacenes observables. La estructura del estado está desnormalizada y a menudo profundamente anidada.
  • El estado es mutable. Puede modificarse directamente, pero se recomienda hacerlo mediante funciones de acción.
  • Como dice la documentación: “MobX vuelve a simplificar la gestión de los estados abordando el problema de fondo: hace imposible producir un estado incoherente”
  • Todas las derivaciones se actualizan automática y atómicamente cuando el estado cambia.

Almacén Redux

Como se ha dicho antes, Redux almacena los datos de estado en un único almacén global, que es la única fuente de verdad. Para gestionarlo se utilizan reductores que toman un objeto de acción y devuelven una copia actualizada del estado. El objeto de acción es un simple objeto javascript que contiene el campo de tipo de acción y los campos de carga útil. Los reductores permiten dividir un objeto de estado en unidades lógicas separadas, como artistReducer, articlesReducer, profileReducer, que luego se combinan en un solo objeto de estado utilizando combineReducers. El almacén dispone de métodos dispatch y subscribe para gestionar el estado y responder a los cambios. Si, después de llamar a dispatch, el estado se actualiza, se notifica a todos los suscriptores. Sin embargo, se necesitará mucho código boilerplate para describir el almacén, lo que supone un gran inconveniente para los proyectos pequeños. Un ejemplo de almacén en Redux:

Tienda MobX

Una aplicación que utiliza MobX, tiende a tener múltiples almacenes que dividen el estado en trozos lógicos, como un modelo de dominio o el estado de la interfaz de usuario. Esto le permite organizar convenientemente su estructura de estado y reutilizar los almacenes individuales en otras aplicaciones. MobX tiene un nivel de abstracción bastante alto, que reduce significativamente el código boilerplate en comparación con Redux. Esto permite crear rápidamente almacenes utilizando anotaciones @observable y @computed o las funciones makeObservable y makeAutoObservable. Cualquier cambio en el estado puede realizarse directamente, como artistStore.artists.push(artist), o, como se recomienda, de forma más explícita utilizando @action como se muestra en el ejemplo siguiente. La forma más sencilla de reaccionar a los cambios en la tienda es crear una reacción pasando una llamada de retorno a la función de ejecución automática. La reacción será llamada cuando se cree por primera vez y siempre que los valores observables y computados cambien en el almacén. La principal desventaja de este enfoque es que cuando las aplicaciones comienzan a crecer hasta convertirse en más complejas, da lugar a relaciones poco evidentes y difíciles de depurar entre los almacenes. El siguiente ejemplo describe un almacén MobX similar al almacén Redux presentado anteriormente:

Popularidad y compatibilidad

A juzgar por el potente apoyo de la comunidad, Redux es sin duda más popular que MobX. En esta biblioteca, cualquier desarrollador puede encontrar soluciones a los problemas relacionados con Redux y utilizar una cómoda herramienta para depurar el estado de Redux DevTools. Esto simplifica el proceso de dominio de la biblioteca. Sin embargo, la necesidad de escribir una gran cantidad de código boilerplate y muchas bibliotecas de utilidad y soluciones como redux-saga, redux-thunk, reseleccionar, normalizr, middlewares, etc., es la principal causa de los dolores de cabeza de la gente en el camino de su dominio. Mientras tanto, MobX ofrece una alta abstracción en las anotaciones, lo que permite pasar rápidamente de aprender a trabajar con la biblioteca.

MobX y Redux son bibliotecas independientes que son compatibles con casi todos los frameworks de UI. En el caso de soluciones populares como React, los paquetes preparados facilitan la conexión y la gestión de los estados, como mobx-react o react-redux.

Depuración

La depuración de estados en Redux es increíblemente flexible y transparente gracias a su bajo nivel de abstracción, el paradigma Flux y el práctico Redux DevTools. Redux DevTools proporciona la más amplia funcionalidad para la depuración de estado, incluyendo el viaje en el tiempo para los cambios de estado, la importación/exportación de estado como un archivo regular .json, la generación de autotest, la visualización de estado como un árbol, gráficos, sólo para nombrar algunos. MobX también tiene una utilidad de depuración de estado – MobX DevToolspero su funcionalidad es mucho más limitada en comparación con la utilidad para Redux. Permite a los usuarios ver el árbol de estado del repositorio y captar los cambios de estado y el rediseño de los componentes. Además, MobX viene con una serie de utilidades como trace y spy que facilitan la depuración de estado.

Palabras finales

Este artículo considera dos bibliotecas destinadas a resolver un mismo problema, pero con métodos diferentes. Hemos esbozado los pros y los contras de cada biblioteca – la elección es suya. Decídase por Redux si su prioridad es trabajar con un almacén de estados flexible, escalable, depurable y más popular, y si no le supone un problema el tener mucho código boilerplate. Sin embargo, para el almacenamiento de implementación rápida en un pequeño MVP o proyecto PoC, se debe adoptar MobX. A continuación hay una breve lista de pros y contras que debería ayudarle a decidir sobre la herramienta adecuada para su tarea.

MobX Redux
Pros
  • Fácil de aprender
  • Una pequeña cantidad de código boilerplate
  • Soporte completo de TypeScript
  • Gran apoyo de la comunidad
  • Fácil depuración y pruebas
  • Flexibilidad y extensibilidad gracias a las funciones reductoras puras y a los middlewares
Contras
  • Depuración desafiante
  • Alto nivel de libertad en términos de almacenamiento, estructuración y procesamiento de datos
  • Escalado complicado que viene con el crecimiento de un proyecto
  • Mucho código repetitivo
  • Falta de efectos secundarios fuera de la caja
  • La necesidad de aprender muchas bibliotecas adicionales
MobX

Pros
  • Fácil de aprender
  • Una pequeña cantidad de código boilerplate
  • Soporte completo de TypeScript
Contras
  • Depuración desafiante
  • Alto nivel de libertad en términos de almacenamiento, estructuración y procesamiento de datos
  • Complicado escalado que viene con el crecimiento de un proyecto
Redux

Pros
  • Gran apoyo de la comunidad
  • Fácil depuración y pruebas
  • Flexibilidad y extensibilidad gracias a las funciones reductoras puras y a los middlewares
Contras
  • Mucho código repetitivo
  • Falta de efectos secundarios fuera de la caja
  • La necesidad de aprender muchas bibliotecas adicionales