Contribuye

Herencia

Redux tiene una herencia mixta. Es similar a ciertos patrones y tecnologías, pero también es diferente en varias formas importantes. Vamos a ver las similitudes y diferencias debajo.

Flux

Puede Redux ser considerado una implementación de Flux? y no.

(No te preocupes, los creadores de Flux lo aprueba, si es lo que necesitas saber.)

Redux se inspiro en muchas de las cualidades importantes de Flux. Como Flux, Redux te hacer concentrar la lógica de actualización de modelos en una capa específica de tu aplicación ("stores" en Flux, "reducers" en Redux). En vez de dejar al código de la aplicaciǿn modificar los datos directamente, ambos te hacen describir cada mutación como objetos planos llamados "acciones".

A diferencia de Flux, en Redux no existe el concepto de Dispatcher. Esto es porque se basa en funciones puras en vez de emisores de ventos, y las funciones puras son fáciles de componer y no necesitan entidades adicionales para controlarlas. Dependiendo de como veas Flux, puedes ver esto tanto como una desviación o un detalle de implementación. Flux siempre fue descripto como (state, action) => state. En ese sentido, Redux es una verdadera arquitectura Flux, pero más simple gracias a las funciones puras.

Otra diferencia importante con Flux es que Redux asume que nunca modificas los datos. Puede usar objetos planos o arrays para tu estado y esta perfecto, pero modificarlos dentro de los reducers no es recomendable. Siempre deberías devolver un nuevo objeto, lo cual es simple con la propuesta del operador spread, o con librerías como Immutable.

Mientras que es tecnicamente posible escribir reducers impuros que modifican los datos en algunos por razones de rendimiento, desalentamos activamente hacer eso. Características de desarrollo como time travel, registrar/rehacer, o hot reloading pueden romperse. Además características como inmutabilidad no parecen causar problemas de rendimiento en aplicaciones reales, ya que, como Om demostró, incluso si pierdes la posibilidad de usar asignación en objetos, todavía ganas por evitar re-renders y recalculos caros, debido a que sabes exactamente que cambio gracias a los reducers puros.

Elm

Elm es un lenguaje de programación funcional inspirado por Haskell y creado por Evan Czaplicki. Utiliza una arquitectura 'modelo vista actualizador", donde el actualizador tiene el siguiente formato: (action, state) => state. Los "actualizadores" de Elm sirven para el mismo propósito que los reducers en Redux.

A diferencia de Redux, Elm es un lenguaje, así que puede beneficiarse de de muchas cosas como pureza forzada, tipado estático, inmutabilidad, y coincidencia de patrones (usando la expresión case). Incluso si no planeas usar Elm, deberías leer sobre la arquitectura de Elm, y jugar con eso. Hay un interesante playground de librerías de JavaScript que implementa ideas similares. ¡Debemos mirar ahí por inspiración en Redux! Una forma de acercarnos al tipado estático de Elm es usando una solución de tipado gradual como Flow.

Immutable

Immutable es una librería de JavaScript que implementa estructuras de datos persistentes. Es una API JavaScript idiomática y performante.

Immutable y la mayoría de las librerías similares son ortogonales a Redux. ¡Sientete libre de usarlos juntos!

Redux no se preocupa por si guardas el estado en objetos planos, objetos de Immutable o cualquier otra cosa. Probablemente quieras un mecanismo de (de)serialización para crear aplicaciones universales y rehidratar su estado desde el servidor, pero aparte de eso, puedes usar cualquier librería de almacenamiento de datos mientras soporte inmutabilidad. Por ejemplo, no tiene sentido usar Backbone para tu estado de Redux, ya que estos son mutables.

Ten en cuenta que que incluso si tu librería inmutable soporta punteros, no deberías usarlos en una aplicación de Redux. Todo el árbol de estado debería ser considerado de solo lectura, y deberías usar Redux para actualizar el estado, y suscribirse a los cambios. Por lo tanto, actualizar mediante recuerdos no tiene sentido en Redux. Si tu único caso de uso para los punteros es desacoplar el árbol de estado del el árbolde UI y gradualmente refinar tus punteros, deberías revisar los selectores mejor. Los selectores son funciones getter combinables. Mira reselect para una muy buena y concisa implementación de selectores combinables.

Baobab

Baobab es otra popular librería para implementar inmutabilidad para actualizar objetos planos en JavaScript. Aunque puedes usarlo con Redux, hay muy pocos beneficios de usarlos juntos.

La mayorías de las funcionalidades que provee Baobab están relacionados con actualizar los datos con punteros, pero Redux impone que la única forma de actualizar los datos es despachando acciones. Por lo tanto, resuelven el mismo problema de forma diferente, y no se complementar uno con otro.

A diferencia de Immutable, Baobab todavía no implemente ninguna estructura de datos especialmente eficiente, así que no ganas nada realmente por usarlo junto a Redux. Es más fácil simplemente usar objetos planos en su lugar.

Rx

Reactive Extensions (y su reescritura moderna en proceso) es una formas magnífica de manejar la complejidad de aplicaciones asíncronas. De hecho hay un esfuerzo de crear una librería para controlar la interacción entre humano y computadora como observables independientes.

¿Tiene sentido usar Redux junto con Rx? ¡Seguro! Funcionan genial juntos. Por ejemplo, es fácil exponer el store de Redux como un observable:

function toObservable(store) {
  return {
    subscribe({ onNext }) {
      let dispose = store.subscribe(() => onNext(store.getState()));
      onNext(store.getState());
      return { dispose };
    },
  };
}

De forma similar, puedes componer diferentes streams asíncronos para convertirlos en acciones antes de enviarlos al store.dispatch().

La pregunta es: de verdad necesitas REdux si ya usar Rx? Probablemente no. No es dificil reimplementar Redux en Rx. Algunos dicen, que son solo 2 líneas usando el método .scan() de Rx. ¡Y probablemente lo sea!

Si tienes dudas, revisa el código fuente de Redux (no hay mcuho ahí), así como su ecosistema (por ejemplo, las herramientas de desarrolladores). Si no te interesa tanto eso y quieres que los datos reactivos simplemente fluyan, probablemente quieras usar algo como Cycle en su lugar, o incluso combinarlos con Redux. ¡Déjanos saber como resulta eso!