- Tabla de Contenidos#
- ¿Por qué debería usar una biblioteca centrada en lo inmutable como Immutable.JS?
- Más información#
- ¿Por qué debería elegir Immutable.JS como una biblioteca inmutable?#
- Inmutabilidad garantizada#
- Rich API#
- Rendimiento#
- Más información#
- ¿Cuáles son los problemas con el uso de Immutable.JS?#
- Difícil de interoperar con#
- Una vez utilizado, Immutable.JS se extenderá por toda su base de código#
- No hay operadores de desestructuración o propagación#
- No es adecuado para los valores pequeños que cambian a menudo#
- Difícil de depurar#
- Rompe las referencias a los objetos, causando un bajo rendimiento#
- Más información#
- ¿Vale la pena usar Immutable.JS? Hay varias compensaciones y opiniones a considerar, pero hay muchas buenas razones para usar Immutable.JS. No subestime la dificultad de tratar de localizar una propiedad de su árbol de estado que ha sido mutada inadvertidamente.
- Más información#
- ¿Cuáles son algunas de las mejores prácticas opinables para usar Immutable.JS con Redux?#
- Nunca mezcles objetos JavaScript planos con Immutable.JS#
- Más información#
- Haz que todo tu árbol de estado Redux sea un objeto Immutable.JS#
- Más información#
- Usa Immutable.JS en todas partes excepto en tus componentes tontos#
- Información adicional#
- Limita tu uso de toJS()#
- Más información#
- Tus selectores deben devolver objetos inmutables.JS#
- Usa objetos Immutable.JS en tus componentes inteligentes#
- Más información#
- Nunca uses toJS() en mapStateToProps#
- Más información#
- Nunca uses Immutable.JS en tus componentes tontos#
- Más información#
- Usa un Componente de Orden Superior para convertir los props Immutable.JS de tu Componente Inteligente en los props JavaScript de tu Componente Mudo#
- Más información#
- Usa la extensión de Chrome Immutable Object Formatter para ayudar a la depuración#
Tabla de Contenidos#
- ¿Por qué debería usar una librería enfocada a la inmutabilidad como Immutable.JS?
- ¿Por qué debería elegir Immutable.JS como una librería inmutable?
- ¿Cuáles son los problemas de usar Immutable.JS?
- ¿Vale la pena el esfuerzo de Immutable.JS?
- ¿Cuáles son algunas de las mejores prácticas para usar Immutable.JS con Redux?
¿Por qué debería usar una biblioteca centrada en lo inmutable como Immutable.JS?
Las bibliotecas centradas en lo inmutable como Immutable.JS han sido diseñadas para superar los problemas de inmutabilidad inherentes a JavaScript, proporcionando todos los beneficios de la inmutabilidad con el rendimiento que su aplicación requiere.
Si decide utilizar una biblioteca de este tipo, o seguir con JavaScript, depende de lo cómodo que se sienta con la adición de otra dependencia a su aplicación, o de lo seguro que esté de poder evitar las trampas inherentes al enfoque de JavaScript para la inmutabilidad.
Cualquiera que sea la opción que elija, asegúrese de estar familiarizado con los conceptos de inmutabilidad, efectos secundarios y mutación. En particular, asegúrese de tener una comprensión profunda de lo que JavaScript hace al actualizar y copiar valores con el fin de protegerse contra las mutaciones accidentales que degradarán el rendimiento de su aplicación, o romperlo por completo.
Más información#
Documentación
- Recetas: inmutabilidad, efectos secundarios y mutación
Artículos
- Introducción a Immutable.js y conceptos de programación funcional
- Pros y contras del uso de la inmutabilidad con React.js
¿Por qué debería elegir Immutable.JS como una biblioteca inmutable?#
Immutable.JS fue diseñado para proporcionar inmutabilidad de una manera performante en un esfuerzo por superar las limitaciones de la inmutabilidad con JavaScript. Sus principales ventajas incluyen:
Inmutabilidad garantizada#
Los datos encapsulados en un objeto Immutable.JS nunca se mutan. Siempre se devuelve una nueva copia. Esto contrasta con JavaScript, en el que algunas operaciones no mutan sus datos (por ejemplo, algunos métodos de Array, incluyendo map, filter, concat, forEach, etc.), pero algunos lo hacen (pop, push, splice, etc. de Array).
Rich API#
Immutable.JS proporciona un rico conjunto de objetos inmutables para encapsular sus datos (e.g. Mapas, Listas, Conjuntos, Registros, etc.), y un amplio conjunto de métodos para manipularlos, incluyendo métodos para ordenar, filtrar y agrupar los datos, invertirlos, aplanarlos y crear subconjuntos.
Rendimiento#
Immutable.JS hace mucho trabajo detrás de las escenas para optimizar el rendimiento. Esta es la clave de su poder, ya que el uso de estructuras de datos inmutables puede implicar una gran cantidad de copias costosas. En particular, la manipulación inmutable de conjuntos de datos grandes y complejos, como un árbol de estado Redux anidado, puede generar muchas copias intermedias de objetos, que consumen memoria y ralentizan el rendimiento mientras el recolector de basura del navegador lucha por limpiar las cosas.
Immutable.JS evita esto compartiendo inteligentemente estructuras de datos bajo la superficie, minimizando la necesidad de copiar datos. También permite llevar a cabo complejas cadenas de operaciones sin crear innecesarios (y costosos) datos intermedios clonados que serán rápidamente desechados.
Nunca ves esto, por supuesto – los datos que das a un objeto Immutable.JS nunca se mutan. Más bien, son los datos intermedios generados dentro de Immutable.JS a partir de una secuencia encadenada de llamadas a métodos los que están libres de ser mutados. Por lo tanto, usted obtiene todos los beneficios de las estructuras de datos inmutables con ninguno (o muy poco) de los potenciales golpes de rendimiento.
Más información#
Artículos
- Immutable.js, estructuras de datos persistentes y compartición estructural
- PDF: JavaScript Immutability – Don’t go changing
Libraries
- Immutable.js
¿Cuáles son los problemas con el uso de Immutable.JS?#
Aunque potente, Immutable.JS necesita ser utilizado con cuidado, ya que viene con problemas propios. Tenga en cuenta, sin embargo, que todos estos problemas se pueden superar fácilmente con una codificación cuidadosa.
Difícil de interoperar con#
JavaScript no proporciona estructuras de datos inmutables. Como tal, para que Immutable.JS proporcione sus garantías de inmutabilidad, sus datos deben estar encapsulados dentro de un objeto Immutable.JS (como un Map
o un List
, etc.). Una vez que está contenida de esta manera, es difícil que esos datos interoperen con otros objetos JavaScript simples.
Por ejemplo, ya no podrá hacer referencia a las propiedades de un objeto a través de la notación estándar de puntos o corchetes de JavaScript. En su lugar, debe hacer referencia a ellas a través de los métodos get()
o getIn()
de Immutable.JS, que utilizan una sintaxis incómoda que accede a las propiedades a través de una matriz de cadenas, cada una de las cuales representa una clave de propiedad.
Por ejemplo, en lugar de myObj.prop1.prop2.prop3
, utilizaría myImmutableMap.getIn()
.
Esto hace que sea incómodo interoperar no sólo con tu propio código, sino también con otras bibliotecas, como lodash o ramda, que esperan objetos JavaScript planos.
Nota que los objetos Immutable.JS tienen un método toJS()
, que devuelve los datos como una estructura de datos JavaScript simple, pero este método es extremadamente lento, y su uso extensivo anulará los beneficios de rendimiento que Immutable.JS proporciona
Una vez utilizado, Immutable.JS se extenderá por toda su base de código#
Una vez que encapsule sus datos con Immutable.JS, tienes que usar los accesores de propiedad get()
o getIn()
de Immutable.JS para acceder a ellos.
Esto tiene el efecto de propagar Immutable.JS a través de toda tu base de código, incluyendo potencialmente tus componentes, donde puedes preferir no tener tales dependencias externas. Toda su base de código debe saber qué es, y qué no es, un objeto Immutable.JS. También hace que la eliminación de Immutable.JS de su aplicación sea difícil en el futuro, si alguna vez lo necesita.
Este problema se puede evitar desacoplando la lógica de su aplicación de sus estructuras de datos, como se indica en la sección de mejores prácticas a continuación.
No hay operadores de desestructuración o propagación#
Debido a que debe acceder a sus datos a través de Immutable.JS, ya no puede utilizar el operador de desestructuración de JavaScript (o el operador de propagación de objetos propuesto), lo que hace que su código sea más verboso.
Imutable.JS funciona mejor para las colecciones de datos, y cuanto más grande, mejor. Puede ser lento cuando sus datos comprenden un montón de pequeños y simples objetos JavaScript, con cada uno de ellos comprendiendo unas pocas claves de valores primitivos.
Nótese, sin embargo, que esto no se aplica al árbol de estado de Redux, que (normalmente) se representa como una gran colección de datos.
Difícil de depurar#
Los objetos de Immutable.JS, como Map
, List
, etc., pueden ser difíciles de depurar, ya que la inspección de un objeto de este tipo revelará toda una jerarquía anidada de propiedades específicas de Immutable.JS que no le interesan, mientras que sus datos reales que le interesan están encapsulados a varias capas de profundidad.
Para resolver este problema, utilice una extensión del navegador como Immutable.js Object Formatter, que hace aflorar sus datos en Chrome Dev Tools, y oculta las propiedades de Immutable.JS al inspeccionar sus datos.
Rompe las referencias a los objetos, causando un bajo rendimiento#
Una de las ventajas clave de la inmutabilidad es que permite la comprobación de la igualdad superficial, lo que mejora drásticamente el rendimiento.
Si dos variables diferentes hacen referencia al mismo objeto inmutable, entonces una simple comprobación de la igualdad de las dos variables es suficiente para determinar que son iguales, y que el objeto al que ambos hacen referencia no se cambia. La comprobación de la igualdad nunca tiene que comprobar los valores de cualquiera de las propiedades del objeto, ya que es, por supuesto, inmutable.
Sin embargo, la comprobación superficial no funcionará si sus datos encapsulados dentro de un objeto Immutable.JS es en sí mismo un objeto. Esto se debe a que el método toJS()
de Immutable.JS, que devuelve los datos contenidos dentro de un objeto Immutable.JS como un valor JavaScript, creará un nuevo objeto cada vez que sea llamado, y así romperá la referencia con los datos encapsulados.
En consecuencia, llamar a toJS()
dos veces, por ejemplo, y asignar el resultado a dos variables diferentes hará que falle una comprobación de igualdad en esas dos variables, aunque los valores del objeto en sí no hayan cambiado.
Esto es un problema particular si se utiliza toJS()
en la función mapStateToProps
de un componente envuelto, ya que React-Redux compara superficialmente cada valor en el objeto props devuelto. Por ejemplo, el valor referenciado por la proposición todos
devuelta desde mapStateToProps
siempre será un objeto diferente, y por lo tanto fallará una comprobación de igualdad superficial.
Copiar
Cuando la comprobación superficial falla, React-Redux hará que el componente se vuelva a renderizar. El uso detoJS()
enmapStateToProps
de esta manera, por lo tanto, siempre causará que el componente se vuelva a renderizar, incluso si el valor nunca cambia, impactando fuertemente en el rendimiento.
Esto se puede evitar mediante el uso de toJS()
en un componente de orden superior, como se discute en la sección de mejores prácticas a continuación.
Más información#
Artículos
- Immutable.js, estructuras de datos persistentes y compartición estructural
- Estructuras de datos inmutables y JavaScript
- React.js pure render performance anti-pattern
- Building Efficient UI with React and Redux
Chrome Extension
- Immutable Object Formatter
¿Vale la pena usar Immutable.JS? Hay varias compensaciones y opiniones a considerar, pero hay muchas buenas razones para usar Immutable.JS. No subestime la dificultad de tratar de localizar una propiedad de su árbol de estado que ha sido mutada inadvertidamente.
Los componentes se volverán a renderizar cuando no deban, y se negarán a renderizar cuando deban, y el seguimiento del error que causa el problema de renderización es difícil, ya que el componente que se renderiza incorrectamente no es necesariamente aquel cuyas propiedades están siendo mutadas accidentalmente.
Este problema es causado predominantemente por la devolución de un objeto de estado mutado desde un reductor Redux. Con Immutable.JS, este problema simplemente no existe, eliminando así toda una clase de errores de tu aplicación.
Esto, junto con su rendimiento y su rica API para la manipulación de datos, es la razón por la que Immutable.JS merece el esfuerzo.
Más información#
Documentación
- Solución de problemas: No pasa nada cuando despacho una acción
¿Cuáles son algunas de las mejores prácticas opinables para usar Immutable.JS con Redux?#
Immutable.JS puede proporcionar importantes mejoras de fiabilidad y rendimiento a tu app, pero debe usarse correctamente. Si eliges usar Immutable.JS (y recuerda, no estás obligado a hacerlo, y hay otras librerías inmutables que puedes usar), sigue estas buenas prácticas de opinión, y podrás sacarle el máximo partido, sin tropezar con ninguno de los problemas que puede causar potencialmente.
Nunca mezcles objetos JavaScript planos con Immutable.JS#
Nunca dejes que un objeto JavaScript plano contenga propiedades Immutable.JS. Igualmente, nunca dejes que un objeto Immutable.JS contenga un objeto JavaScript plano.
Más información#
Artículos
- Estructuras de datos inmutables y JavaScript
Haz que todo tu árbol de estado Redux sea un objeto Immutable.JS#
Para una aplicación Redux, todo tu árbol de estado debe ser un objeto Immutable.JS, sin usar objetos JavaScript planos.
-
Crea el árbol usando la función
fromJS()
de Immutable.JS. -
Usa una versión Immutable.JS de la función
combineReducers
, como la de redux-immutable, ya que Redux espera que el árbol de estado sea un objeto JavaScript plano. -
Cuando se añaden objetos JavaScript a un mapa o lista de Immutable.JS usando Immutable.JS’s
update
,merge
oset
métodos, asegúrese de que el objeto que se añade se convierte primero en un objeto Inmutable utilizandofromJS()
.
Ejemplo
Copiar
Más información#
Artículos
- Estructuras de datos inmutables y JavaScript
Bibliotecas
- redux-immutable
Usa Immutable.JS en todas partes excepto en tus componentes tontos#
Usar Immutable.JS en todas partes mantiene el rendimiento de tu código. Úsalo en tus componentes inteligentes, en tus selectores, en tus sagas o thunks, en los creadores de acciones y, especialmente, en tus reductores.
No uses, sin embargo, Immutable.JS en tus componentes tontos.
Información adicional#
Artículos
- Estructuras de datos inmutables y JavaScript
- Componentes inteligentes y tontos en React
Limita tu uso de toJS()#
toJS()
es una función cara y anula el propósito de usar Immutable.JS. Evite su uso.
Más información#
Discusiones
- Lee Byron en Twitter: «Consejo de perfeccionamiento para #immutablejs…»
Tus selectores deben devolver objetos inmutables.JS#
Siempre. Esta práctica tiene varias ventajas:
- Evita las repeticiones innecesarias causadas por la llamada a
.toJS()
en los selectores (ya que.toJS()
siempre devolverá un nuevo objeto).- Es posible memoizar los selectores donde se llama a
.toJS()
, pero es redundante cuando basta con devolver objetos Immutable.js sin memoizar.
- Es posible memoizar los selectores donde se llama a
- Establece una interfaz consistente para los selectores; no tendrás que estar pendiente de si se devolverá un objeto Immutable.js o un objeto JavaScript plano.
Usa objetos Immutable.JS en tus componentes inteligentes#
Los componentes inteligentes que acceden al almacén a través de la función connect
de React Redux deben usar los valores Immutable.JS devueltos por tus selectores. Asegúrese de evitar los problemas potenciales que esto puede causar con el re-renderizado innecesario del componente. Memoize sus selectores utilizando una biblioteca como reselect si es necesario.
Más información#
Documentación
- Recetas: Cálculo de datos derivados
- Preguntas frecuentes: Datos inmutables
- Documentación de Reselect: ¿Cómo uso Reselect con Immutable.js?
Artículos
- Patrones y antipatrones Redux
Bibliotecas
- Reselect: Librería de selectores para Redux
Nunca uses toJS() en mapStateToProps#
Convertir un objeto Immutable.JS en un objeto JavaScript usando toJS()
devolverá un nuevo objeto cada vez. Si usted hace esto en mapStateToProps
, hará que el componente crea que el objeto ha cambiado cada vez que el árbol de estado cambia, y así desencadenar un innecesario re-render.
Más información#
Documentación
- FAQ: Immutable Data
Nunca uses Immutable.JS en tus componentes tontos#
Tus componentes tontos deben ser puros; es decir, deben producir la misma salida dada la misma entrada, y no tener dependencias externas. Si pasas a un componente de este tipo un objeto Immutable.JS como prop, lo haces dependiente de Immutable.JS para extraer el valor de la prop y manipularlo de otra manera.
Tal dependencia hace que el componente sea impuro, hace que las pruebas del componente sean más difíciles, y hace que la reutilización y refactorización del componente sea innecesariamente difícil.
Más información#
Artículos
- Estructuras de datos inmutables y JavaScript
- Componentes inteligentes y tontos en React
- Consejos para una mejor arquitectura Redux: Lecciones para la escala empresarial
Usa un Componente de Orden Superior para convertir los props Immutable.JS de tu Componente Inteligente en los props JavaScript de tu Componente Mudo#
Algo tiene que mapear los props Immutable.JS de tu Componente Inteligente a los props JavaScript puros usados en tu Componente Mudo. Ese algo es un Componente de Orden Superior (HOC) que simplemente toma los props Immutable.JS de su Componente Inteligente, y los convierte usando toJS()
a props de JavaScript puro, que luego son pasados a su Componente Mudo.
Un ejemplo de tal HOC sigue. Un HOC similar está disponible como un paquete NPM para su conveniencia: with-immutable-props-to-js.
Copiar
Y así es como lo usarías en tu componente inteligente:
Copiar
Al convertir los objetos Immutable.JS en valores JavaScript planos dentro de un HOC, conseguimos la portabilidad del Dumb Component, pero sin los golpes de rendimiento de usartoJS()
en el Smart Component.
Nota: si tu app requiere un alto rendimiento, puede que necesites evitar toJS()
por completo, y así tendrás que usar Immutable.JS en tus dumb components. Sin embargo, para la mayoría de las aplicaciones este no será el caso, y los beneficios de mantener Immutable.JS fuera de sus componentes tontos (mantenibilidad, portabilidad y pruebas más fáciles) superarán con creces cualquier mejora de rendimiento percibida por mantenerlo dentro.
Además, el uso de toJS
en un Componente de Orden Superior no debería causar mucha, o ninguna, degradación del rendimiento, ya que el componente sólo será llamado cuando los accesorios del componente conectado cambien. Al igual que con cualquier problema de rendimiento, realice primero comprobaciones de rendimiento antes de decidir qué optimizar.
Más información#
Documentación
- React: Componentes de orden superior
Artículos
- React Componentes de orden superior en profundidad
Discusiones
- Redacción: acemarke y cpsubrian comentan sobre Dan Abramov: Redux no es una arquitectura ni un patrón de diseño, es sólo una biblioteca.
Gistas
- cpsubrian: React decorators for redux/react-router/immutable ‘smart’ components
Usa la extensión de Chrome Immutable Object Formatter para ayudar a la depuración#
Instala el Immutable Object Formatter , e inspecciona tus datos de Immutable.JS sin ver el ruido de las propias propiedades de los objetos de Immutable.JS.