Redux: ¿Por qué no se puede mutar el estado ...

Creado en 20 sept. 2015  ·  13Comentarios  ·  Fuente: reduxjs/redux

Hola,

Leí con interés sobre inmutable y cómo no debes mutar tu estado. Entiendo hasta cierto punto por qué eso es, sin embargo, mi lado "preocupado por el tiempo dedicado a la creación de nuevos objetos" es que no entiendo en JS qué tan rápido / lento es esto, o me falta algo más.

Por lo general, crear un nuevo objeto, más o menos clonar un objeto antiguo al nuevo más las adiciones (o sustracciones) del nuevo estado me parece que llevaría más tiempo que simplemente modificar el estado existente. Entonces, estoy tratando de comprender por qué lo inmutable es tan importante y ¿afecta a algo más en la cadena que simplemente no estoy viendo?

Además ... Creo que mucho de lo que ofrece Reduct podría agregarse al react-core, y tal vez incluso aprovechar su motor de diferenciación DOM ... tal vez incluso para ayudar a determinar si el estado debe mutar o no. No estoy seguro de si el proceso de cambio de estado sería más rápido o más lento que diferenciar el estado con el nuevo estado y cambiar (mutar) solo las partes del objeto de estado real que deberían cambiar.

Soy relativamente nuevo en todo esto, así que perdóname si me pierdo algo sobre la noción de estado no mutante. Me encanta la idea de que los componentes solo deben representar datos inmutables ... pero, de nuevo, al componente, no le importa ni sabe si es inmutable o no ... son solo datos que se pasan de algún lugar, así que estoy luchando con un bit con todo el estado inmutable vs mutable.

question

Comentario más útil

Solo para aclarar: el estado no está profundamente clonado en cada acción. Solo se clonan las partes que cambiaron (nuevamente, no profundamente, depende de lo que haya cambiado). Por ejemplo, cuando se edita una tarea en la aplicación TodoMVC, solo se clona ese objeto de tarea. El resto de los objetos de tareas pendientes son iguales. Por supuesto, se crea una nueva matriz de lista de tareas pendientes raíz, apuntando al nuevo objeto, pero los objetos en sí no se clonan si no han cambiado. Por tanto, no es tan caro como parece. Además, cuando se vuelve costoso (por ejemplo, cambios rápidos de matriz), puede comenzar a usar una biblioteca como Immutable.js que tiene una copia muy rápida gracias al uso compartido estructural. Con Immutable.js, copiar incluso matrices grandes no es realmente tan caro porque se reutilizan grandes porciones de memoria. Finalmente, ya sea con o sin Immutable.js, la inmutabilidad nos ayuda a volver a renderizar la aplicación de manera eficiente porque sabemos _qué exactamente_ ha cambiado gracias a que los objetos no están mutados.

Todos 13 comentarios

Se trata de previsibilidad y fiabilidad.

Los reductores en redux son funciones puras, lo que significa que no tienen efectos secundarios. Tan pronto como empiece a observar algún estado externo de esas funciones, dejarán de ser puras. Y si no son puros, pueden ser poco fiables. Y eso causa errores, muchos de los cuales pueden ser _muy_ difíciles de rastrear.

Descubrí que al escribir funciones puras, produzco menos errores en mi código y soy más productivo. Y la recarga de módulo en caliente (habilitada mediante el uso de funciones puras) es un turbocompresor además de esa productividad.

Y recibe funciones gratuitas como el viaje en el tiempo, que es muy útil.

Cerrando como duplicado de # 328.

Solo para aclarar: el estado no está profundamente clonado en cada acción. Solo se clonan las partes que cambiaron (nuevamente, no profundamente, depende de lo que haya cambiado). Por ejemplo, cuando se edita una tarea en la aplicación TodoMVC, solo se clona ese objeto de tarea. El resto de los objetos de tareas pendientes son iguales. Por supuesto, se crea una nueva matriz de lista de tareas pendientes raíz, apuntando al nuevo objeto, pero los objetos en sí no se clonan si no han cambiado. Por tanto, no es tan caro como parece. Además, cuando se vuelve costoso (por ejemplo, cambios rápidos de matriz), puede comenzar a usar una biblioteca como Immutable.js que tiene una copia muy rápida gracias al uso compartido estructural. Con Immutable.js, copiar incluso matrices grandes no es realmente tan caro porque se reutilizan grandes porciones de memoria. Finalmente, ya sea con o sin Immutable.js, la inmutabilidad nos ayuda a volver a renderizar la aplicación de manera eficiente porque sabemos _qué exactamente_ ha cambiado gracias a que los objetos no están mutados.

Ahh ... mira que el último bit tiene sentido ahora ... Supongo que con esto estás diciendo que debido al cambio de renderización del componente debido solo a qué estado cambió, ¿el motor de reacción diff / redraw es más rápido como resultado? Similar supongo que shouldComponentUpdate

Supongo que con esto está diciendo que debido al cambio de renderización del componente debido solo a qué estado cambió, el motor de reaccionar diff / redraw es más rápido como resultado Similar supongo que shouldComponentUpdate

Exactamente, react-redux usa un shouldComponentUpdate agresivo bajo el capó gracias a la garantía de inmutabilidad.

@gaearon ¡ Perdón por necro este un poco! pero su comentario sobre las actualizaciones rápidas de la matriz:

Además, cuando se vuelve costoso (por ejemplo, cambios rápidos de matriz), puede comenzar a usar una biblioteca como Immutable.js que tiene una copia muy rápida gracias al uso compartido estructural.

Estoy buscando usar redux para manejar las actualizaciones de una matriz que va hasta 8000 posiciones y espero que el rendimiento esté en la región de 10-100 cambios por 100 ms. ¿Estoy librando una batalla perdida para tratar de administrar el estado de esa manera usando redux?
Estamos planeando representar al estado a través de un lienzo en lugar del DOM, pero me gustaría saber si, según su experiencia, la frecuencia de las actualizaciones nos causaría un problema o no.

@dougajmcdonald : Mi primera pregunta es, ¿se puede

Más allá de eso, le sugiero que consulte estos recursos sobre el rendimiento relacionado con Redux:

También me complacería conversar más sobre esto en los canales de chat de Reactiflux .

@markerikson Desafortunadamente, sí, el concepto del juego implica muchas actualizaciones rápidas a una estructura de datos relativamente grande.
Me doy cuenta de que no estaba totalmente claro en mi comentario original, cuando digo 10-100 cambios, no todos desencadenarían redibujos. Los cambios 10-100 son los cambios de estado que estarían representados por un solo redibujado por cada 100 ms.
Entonces, mi pregunta es realmente, si tuviera que agrupar mis actualizaciones en 10-100 cambios de estado por 100 ms, ¿la administración de estado dentro de redux podría procesarlos de manera efectiva de una manera que se completaría razonablemente dentro de una ventana de 100 ms para Permita que se vuelva a dibujar sin que las cosas empiecen a retrasarse.
Las actualizaciones de estado implicarían básicamente cambiar 3-4 propiedades en una matriz de tamaño 8000, por lo que estaríamos hablando de crear una nueva matriz 1-10 veces por ms (asumiendo que queremos mantener las cosas inmutables) con algunos cambios en uno de los objetos dentro del índice de la matriz. Los objetos son bastante pequeños (3-4 propiedades, un par de números y un par de cadenas pequeñas)

Es por eso que me pregunté acerca de los beneficios de usar inmutable como sugirió Dan, ya que si podemos reutilizar la mayor cantidad posible de la matriz, esto probablemente mejorará el rendimiento.

@dougajmcdonald : bueno, "la administración del estado en Redux" es realmente solo la función de reducción de una raíz que ha proporcionado :)

Immutable.js no es una fórmula mágica para mejorar el rendimiento. Puede hacer que algunas cosas sean más rápidas y otras más lentas. Tengo varios artículos sobre consideraciones de rendimiento relacionadas con Immutable.js que es posible que desee consultar.

Para ser honesto, dado su caso de uso, en teoría, podría salirse con la suya con la mutación directa más si quisiera. Según mi publicación Idiomatic Redux, Parte 1 - Implementación e intención , el núcleo de Redux en sí no se preocupa en absoluto por la mutación; es principalmente la capa de interfaz de usuario de React-Redux la que lo hace, así como las DevTools. Ahora, la mutación no es la forma en que está _intencionado_ usar Redux, pero es posible.

Mi consejo personal sería empezar de forma sencilla. Solo use objetos y matrices JS simples. Actualícelos de manera inmutable, ya sea "a mano" o usando una de las muchas bibliotecas de utilidades de actualización inmutables disponibles. Vea qué tan bien funciona para usted.

Luego, a partir de ahí, puede realizar un trabajo de optimización adicional en términos de procesamiento por lotes, reducción de envíos, actualización de la lógica, etc.

@markerikson sutil burla tomada en la nariz! : p Sí, tiene razón, el lado reductor de las cosas en este momento es básicamente la creación y destrucción de una matriz bastante grande, pero creo que el problema real es más probable que los bits y sacudidas del ciclo de vida del componente de reacción cuando el objetivo final sea un elemento de lienzo idealmente renderizado a 60 FPS.
Gracias por el punto sobre inmutable y los puntos sobre mutación directa. Leeré un poco y consideraré estos también.
Por el momento, mi proceso de pensamiento es desconectar el estado redux del lienzo y simplemente pasarle mensajes a través de pub / sub (que es como ya lo tenemos conectado) solo con más partes móviles

Estoy pensando en cambiar de:
pubsub> dispatch ()> reducer> redux state> react component stuff> canvas render.

A:
pubsub> estado del componente local> renderizado de lienzo

Seguiré usando redux para el resto de la interfaz de usuario, pero quizás no la parte de lienzo de la aplicación.

Tus preguntas son totalmente válidas. En realidad, la implementación de vuejs de redux llamada vuex funciona bajo el concepto de mutación. Entonces, los 'reductores' de hecho se llaman mutaciones y siempre que modifique el estado en un lugar centralizado, todo debería estar bien. Esto sucede porque vue agrega observadores y otras cosas al estado de la aplicación, por lo que, como mencionaste, tiene más sentido modificar el objeto en lugar de reemplazarlo. Redux es inmutable y al final el rendimiento de ambos enfoques reacciona VS vue las actualizaciones del DOM virtual es casi el mismo en el punto que no es posible decir que para todos los casos uno es mejor que el otro

¿Fue útil esta página
0 / 5 - 0 calificaciones