Redux: Por que o estado não pode ser mutado ...

Criado em 20 set. 2015  ·  13Comentários  ·  Fonte: reduxjs/redux

Oi,

Eu li com interesse sobre imutável e como você não deve mudar seu estado. Eu entendo até certo ponto por que isso é, ainda, o lado "preocupado com o tempo gasto na criação de novos objetos" de mim é não entender em JS como isso é rápido / lento ou estou perdendo outra coisa.

Normalmente, criar um novo objeto, mais ou menos clonar um objeto antigo para o novo mais as novas adições (ou subtrações) de estado, parece-me que consumiria mais tempo do que apenas modificar o estado existente. Portanto, estou tentando entender por que a coisa imutável é tão importante e afeta alguma outra coisa na cadeia que eu simplesmente não estou vendo?

Além disso ... Eu acho que muito do que o Reduct oferece poderia ser adicionado ao react-core, e talvez até mesmo tirar vantagem de seu mecanismo de diffing DOM ... talvez até para ajudar a determinar se o estado deve sofrer mutação ou não. Não tenho certeza se o processo de mutação de estado seria mais rápido ou mais lento do que diferenciar o estado com o novo estado e alterar (mutar) apenas as partes do objeto de estado real que devem mudar.

Sou relativamente novo em tudo isso, então me perdoe se estou perdendo algo em torno da noção de estado não mutante. Eu amo a ideia de que os componentes devem apenas renderizar dados imutáveis ​​... mas, novamente, para o componente, ele não se importa ou sabe se é imutável ou não .. são apenas dados que são transmitidos de algum lugar, então estou lutando contra um bit com todo o estado imutável vs mutável.

question

Comentários muito úteis

Só para esclarecer: o estado não é clonado profundamente em todas as ações. Apenas as partes que mudaram são clonadas (novamente, não profundamente - depende do que mudou). Por exemplo, quando um todo é editado no aplicativo TodoMVC, apenas esse objeto todo é clonado. O resto dos objetos de tarefas são os mesmos. Obviamente, uma nova matriz de lista de tarefas raiz é criada, apontando para o novo objeto, mas os próprios objetos não são clonados se não tiverem mudado. Portanto, não é tão caro quanto pode parecer. Além disso, quando ficar caro (por exemplo, mudanças rápidas de array), você pode começar a usar uma biblioteca como Immutable.js que tem cópias muito rápidas graças ao compartilhamento estrutural. Com Immutable.js, copiar até mesmo matrizes grandes não é tão caro porque grandes pedaços de memória são reutilizados. Finalmente, com ou sem Immutable.js, a imutabilidade nos ajuda a renderizar novamente o aplicativo de forma eficiente, porque sabemos _o que exatamente_ mudou graças aos objetos não sofrerem mutação.

Todos 13 comentários

É tudo uma questão de previsibilidade e confiabilidade.

Redutores em redux são funções puras, o que significa que não têm efeitos colaterais. Assim que você começa a observar algum estado externo a essas funções, elas não são mais puras. E se não forem puros, podem não ser confiáveis. E isso causa bugs, muitos dos quais podem ser _muito_ difíceis de rastrear.

Descobri, escrevendo funções puras, que produzo menos erros em meu código e sou mais produtivo. E o recarregamento de módulo a quente (habilitado usando funções puras) é um turbocompressor no topo dessa produtividade.

E você recebe gratuitamente recursos como viagem no tempo, que é muito útil.

Fechando como duplicata de # 328.

Só para esclarecer: o estado não é clonado profundamente em todas as ações. Apenas as partes que mudaram são clonadas (novamente, não profundamente - depende do que mudou). Por exemplo, quando um todo é editado no aplicativo TodoMVC, apenas esse objeto todo é clonado. O resto dos objetos de tarefas são os mesmos. Obviamente, uma nova matriz de lista de tarefas raiz é criada, apontando para o novo objeto, mas os próprios objetos não são clonados se não tiverem mudado. Portanto, não é tão caro quanto pode parecer. Além disso, quando ficar caro (por exemplo, mudanças rápidas de array), você pode começar a usar uma biblioteca como Immutable.js que tem cópias muito rápidas graças ao compartilhamento estrutural. Com Immutable.js, copiar até mesmo matrizes grandes não é tão caro porque grandes pedaços de memória são reutilizados. Finalmente, com ou sem Immutable.js, a imutabilidade nos ajuda a renderizar novamente o aplicativo de forma eficiente, porque sabemos _o que exatamente_ mudou graças aos objetos não sofrerem mutação.

Ahh .... veja que a última parte faz sentido agora ... Eu presumo que você está dizendo que por causa da mudança de renderização do componente devido apenas a qual estado mudou, o mecanismo de diff / redesenho de reação é mais rápido como resultado? Parecido com o shouldComponentUpdate

Eu suponho que você está dizendo que por causa da mudança de renderização do componente devido apenas ao estado alterado, o mecanismo de diff / redraw de reação é mais rápido como resultado? Parecido com o shouldComponentUpdate

Exatamente, react-redux usa um agressivo shouldComponentUpdate sob o capô graças à garantia de imutabilidade.

@gaearon Desculpe necro este aqui um pouco! mas seu comentário sobre atualizações rápidas de array:

Além disso, quando ficar caro (por exemplo, mudanças rápidas de array), você pode começar a usar uma biblioteca como Immutable.js que tem cópias muito rápidas graças ao compartilhamento estrutural.

Estou pensando em usar o redux para lidar com as atualizações de um array que vai até 8.000 posições e espero que a taxa de transferência esteja na região de 10-100 alterações por 100 ms. Estou lutando uma batalha perdida para tentar gerenciar o estado dessa forma usando redux?
Estamos planejando representar o estado por meio de uma tela em vez do DOM, mas gostaria de entender se, em sua experiência, a frequência das atualizações nos causaria um problema ou não.

@dougajmcdonald : Minha primeira pergunta é: algum desses trabalhos pode ser agrupado de alguma forma? Você _realmente_ precisa representar cada atualização individual como um redesenho separado da IU?

Além disso, sugiro que você analise estes recursos sobre o desempenho relacionado ao Redux:

Eu também ficaria feliz em conversar mais sobre isso nos canais de bate-papo do

@markerikson Infelizmente sim, o conceito do jogo envolve muitas atualizações rápidas em uma estrutura de dados relativamente grande.
Percebo que não fui totalmente claro em meu comentário original, quando digo mudanças 10-100, nem todos eles acionariam redesenhos. As alterações 10-100 são as alterações de estado que seriam representadas por um único redesenho por 100 ms.
Portanto, minha pergunta é realmente, se eu fosse agrupar minhas atualizações em 10-100 mudanças de estado por 100 ms, o gerenciamento de estado dentro do redux seria capaz de processá-las efetivamente de uma forma que seria sensatamente concluída dentro de uma janela de 100 ms para permitir um redesenho sem que as coisas fiquem para trás.
As atualizações de estado envolveriam basicamente a alteração de 3-4 propriedades em um array de tamanho 8000, então estaríamos falando sobre a criação de um novo array 1-10 vezes por ms (assumindo que queremos manter as coisas imutáveis) com algumas mudanças os objetos dentro do índice do array. Os objetos são muito pequenos (3-4 propriedades, alguns números e algumas strings pequenas)

É por isso que me perguntei sobre os benefícios de usar imutável, como Dan sugeriu, pois se pudéssemos reutilizar o máximo possível do array, isso provavelmente melhoraria o desempenho.

@dougajmcdonald : bem, "o gerenciamento de estado no Redux" é realmente apenas a função redutora de raiz que _você_ forneceu :)

Immutable.js não é uma fórmula mágica para melhorar o desempenho. Pode tornar algumas coisas mais rápidas e outras mais lentas. Tenho vários artigos sobre considerações de desempenho relacionadas a Immutable.js que você pode querer dar uma olhada.

Para ser honesto, dado seu caso de uso, você _poderia_ em teoria se safar mais com a mutação direta se quisesse. De acordo com meu post Idiomático Redux, Parte 1 - Implementação e Intenção , o núcleo do Redux em si não se preocupa com a mutação - é principalmente a camada de interface do usuário React-Redux que se preocupa, assim como as DevTools. Agora, a mutação não é como você _intenciona_ usar o Redux, mas é possível.

Meu conselho pessoal seria começar de forma simples. Basta usar objetos e matrizes JS simples. Atualize-os de forma imutável, "manualmente" ou usando uma das muitas bibliotecas de utilitários de atualização imutáveis disponíveis. Veja como isso funciona para você.

Então, a partir daí, você pode fazer um trabalho de otimização adicional em termos de lote, redução de despachos, lógica de atualização e assim por diante.

@markerikson sarcasmo sutil levado no nariz! : p Sim, você está certo, o lado redutor das coisas no momento é basicamente a criação e destruição de uma matriz bastante grande, mas acho que o verdadeiro problema é mais provavelmente os bits e bobs do ciclo de vida do componente de reação quando o objetivo final vai ser um elemento de tela renderizando de maneira ideal a 60 FPS.
Obrigado pelo ponto sobre imutável e pelos pontos sobre mutação direta, irei ler um pouco e considerá-los também.
No momento, meu processo de pensamento é desconectar o estado de redux da tela e apenas passar mensagens para ele via pub / sub (que é como já o conectamos) apenas com mais peças móveis

Estou pensando em mudar de:
pubsub> dispatch ()> redutor> estado redux> material do componente de reação> renderização da tela.

Para:
pubsub> estado do componente local> renderização da tela

Ainda usarei redux para o resto da IU, talvez não para a parte da tela do aplicativo.

Suas perguntas são totalmente válidas. Na verdade, a implementação vuejs de redux chamada vuex funciona sob o conceito de mutação. Portanto, os 'redutores' são na verdade chamados de mutações e contanto que você modifique o estado em um local centralizado, tudo ficará bem. Isso acontece porque o vue adiciona observadores e outras coisas ao estado do aplicativo, então, como você mencionou, faz mais sentido no caso de vue modificar em vez de substituir o objeto. Redux é imutável e no final o desempenho de ambas as abordagens reage ao VS vue virtual DOM updates é basicamente o mesmo no ponto que não é possível dizer que para todos os casos um é melhor que o outro

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

timdorr picture timdorr  ·  3Comentários

captbaritone picture captbaritone  ·  3Comentários

jimbolla picture jimbolla  ·  3Comentários

parallelthought picture parallelthought  ·  3Comentários

caojinli picture caojinli  ·  3Comentários