Redux: Redux Performance com Grande Loja e atualizações frequentes

Criado em 28 jan. 2016  ·  18Comentários  ·  Fonte: reduxjs/redux

Esta é uma pergunta / peça um conselho

Digamos que você tenha um SPA razoavelmente grande com muitos estados, pois há muitas páginas, painéis, subpainéis e muitas outras coisas.

Agora imagine que você projeta seu App usando composição redutora (em vários níveis) e tem a Store bem organizada para facilitar sua vida.

Agora imagine que em um dos painéis você tenha eventos ao vivo. Por exemplo, digamos que você tenha uma lista de 100 itens consistindo de valores de bolsa de valores que são atualizados cada um independentemente 1 vez por segundo. (Desconsidere o problema da rede e assuma que os valores são gerados aleatoriamente).

Acredito que o React seja o caminho a percorrer, pois será inteligente e não renderizará quando não for necessário.

Mas não tenho certeza de como fazer isso funcionar com Redux.

É bom que eu possa usar uma Loja e buscar todos os valores do estoque e armazená-los individualmente acionando ações e assim por diante e tendo uma Loja bem legal com todas as informações muito bem organizadas.

Mas como estou recebendo atualizações muito frequentes, todos os meus redutores (que serão muitos) terão que ser chamados. Sei que a chamada será muito rápida, pois na maioria das vezes copiarei apenas ponteiros de objetos.

De qualquer forma, como meu aplicativo está usando composição tão intensamente, haverá muitas chamadas de função. Isso pode ser ruim, especialmente em dispositivos móveis antigos.

Estou projetando um desses aplicativos e não tenho certeza de como fazer o Redux caber nele (se possível). Talvez você possa dar alguns conselhos valiosos neste momento (acabei de começar a trabalhar nisso). É possível usar (de alguma forma) Lojas diferentes, cada uma conectada apenas a ações diferentes para que eu minimize as chamadas para redutores?

Alguma ideia?
Obrigado

discussion

Comentários muito úteis

O React Redux não usa forceUpdate (). É muito mais cuidadoso :-)
Sim, isso não causará atualizações desnecessárias.

Todos 18 comentários

Este comentário e toda a discussão podem ajudar: https://github.com/rackt/redux/issues/1287#issuecomment -176330134

Obrigado @sompylasar. Minha pergunta é um pouco diferente.

Tenho certeza que os valores atualizados pertencem à Store porque são uma parte fundamental do App.

Digamos que temos uma loja como esta:

store: {
  subStore1: {
    subSubstore1: {}
    ...
    subSubstore10: {}
  },
subStore2: {
    subSubstore1: {}
    ...
    subSubstore10: {}
  }
...
subStore10: {
    subSubstore1: {}
    ...
    subSubstore10: {}
  }
}

(Espero que você tenha a idéia). Na verdade, isso poderia ir ainda mais longe.

Todos os sub-armazenamentos correspondem a interesses muito diferentes do Aplicativo e os sub-armazenamentos são gerenciados por seus próprios redutores.

Em seguida, despacho uma ação que sei que só atualizará substore2: {subSubstore6}.

Por que não simplesmente copiar os ponteiros substore1, substore3, ... substore9 e agora chamar os redutores para os outros subSubstores?

Seria possível dizer de alguma forma combinarRedutores quais ações possíveis desencadearão novos estados em seus redutores filhos?

Ou talvez eu deva considerar o uso de lojas diferentes?

Algum conselho?

Obrigado!

Você pode querer dar uma olhada em https://github.com/omnidan/redux-ignore.

Eu não sabia sobre redux-ignore e definitivamente parece muito promissor!

Talvez esse seja um caminho possível ao desenvolver aplicativos muito grandes (SPA) que lidam com questões ortogonais.

Obrigado pelo conselho!

Mas como estou recebendo atualizações muito frequentes, todos os meus redutores (que serão muitos) terão que ser chamados.

Deixe-me fazer uma correção importante: há apenas uma função de redutor em uma loja Redux. Você pode dividir essa função da maneira que quiser, fazendo uma troca por conveniência, velocidade ou outros fatores, dependendo de suas necessidades. combineReducers é uma maneira comum de lidar com isso, mas não é obrigatório.

Uma ideia que tenho potencialmente um bom desempenho é mapear type para um objeto de manipuladores, codificados por tipo. Esta é uma maneira ingênua de fazer isso:

function buildReducer(handlers) {
  return function reducer(state = initialState, action) {
    return handlers[action.type](state, action);
  }
}

Então, você só executaria um redutor por tipo. Não há um mapeamento 1: 1 de ações para redutores, então você pode precisar reduzir seus redutores para cada tipo, mas você ainda estará reduzindo sua quantidade de overhead.

Claro, as operações DOM e a renderização do React provavelmente serão mais lentas do que alguns JS simples em seus aplicativos de produção. Além disso, a maioria dos mecanismos JS tratará seus redutores como código quente e o JIT os compilará em código nativo, então eu não esperaria que fosse tão lento na prática.

Você também pode depurar renderizações usando redux-batched-subscribe , portanto, caso você tenha várias ações em uma duração muito curta, ela renderizará apenas uma vez.

Veja https://github.com/rackt/react-redux/issues/263 (há um link jsbin lá)

No caso de um aplicativo grande que recebe dados enviados, a estrutura de dados deve residir na árvore de estado?
Se o push estivesse acontecendo a cada segundo, acabaríamos com milhares de história do estado, certo? Eu entendo que os redutores estão apenas mudando uma pequena parte da árvore.

Um efeito colateral disso seria que a tela do devtools teria muitos elementos dom e logo tornaria o navegador mais lento. Chega a um ponto em que fica inutilizável.

Será esta uma suposição correta?

@jorgecarmona Isso afeta apenas as ferramentas de desenvolvimento, que não são usadas na produção. As ferramentas de desenvolvimento, como a maioria das outras ferramentas de depuração ou desenvolvimento, não foram projetadas para ter um bom desempenho. A preocupação aqui é o desempenho no mundo real.

@timdorr aprovado .

Então, de volta ao desempenho no mundo real. Os dados que estão fluindo para o aplicativo a cada segundo devem ser acumulados na árvore de estado? Essa abordagem é escalável?

Se você está apenas anexando a uma matriz e ela nunca se torna esparsa, então deveria ser. Você pode ter algum desempenho O (n), mas também pode resolver isso por meio de pontos de verificação e dividindo as coisas em submatrizes. Não acho que esse seja o seu gargalo tanto quanto a manutenção do DOM de front-end seria.

@timdorr farei alguns testes com essas recomendações.

Obrigado por responder!

@gaearon @timdorr react-ignore ajuda a pular algumas subárvores redutoras para algumas ações, então temos atualização mínima em nossa árvore de estado.
Mas e quanto a todos aqueles componentes que foram inscritos para mudanças de estado.
Eles serão notificados mesmo que o estado associado ao componente não tenha sido alterado.

Existe uma maneira de evitá-lo?

o redutor de reação ajuda a pular algumas subárvores redutoras para algumas ações, portanto, temos uma atualização mínima em nossa árvore de estado.

Não tenho certeza do que você está se referindo. Não tenho conhecimento desse projeto. Você quis dizer https://github.com/omnidan/redux-ignore?

Mas e quanto a todos aqueles componentes que foram inscritos para mudanças de estado.

Use https://github.com/reactjs/react-redux que cuida disso. Ele permite que você especifique partes específicas do estado de seu interesse e cuida para evitar a atualização dos componentes do React quando as partes relevantes não foram alteradas.

Estou encerrando este tópico porque a discussão original se acalmou.

@gaearon

Use https://github.com/reactjs/react-redux que cuida disso. Ele permite que você especifique partes específicas do estado de seu interesse e cuida para evitar a atualização dos componentes do React quando as partes relevantes não foram alteradas.

Eu li o seguinte no doc.

mapStateToProps (state, [ownProps]): stateProps : Se especificado, o componente

Só queria entender completamente o que está acontecendo nos bastidores aqui, então se a loja Redux for atualizada, mas um estado de componente específico não mudou, Redux não acionará o método forceUpdate() para aquele componente.

Se a resposta for sim, você fez meu dia :)

O React Redux não usa forceUpdate (). É muito mais cuidadoso :-)
Sim, isso não causará atualizações desnecessárias.

Mais especificamente: o componente de invólucro gerado pela função connect() React-Redux faz várias verificações para tentar minimizar o número de vezes que seu componente real precisa ser renderizado novamente. Isso inclui uma implementação padrão de shouldComponentUpdate e fazer verificações superficiais de igualdade nas propriedades que vão para o seu componente (incluindo o que é retornado de mapStateToProps ). Portanto, sim, como regra geral, um componente conectado só será renderizado novamente quando os valores do estado que está sendo extraído forem alterados.

: +1: Legal.

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

Questões relacionadas

CellOcean picture CellOcean  ·  3Comentários

rui-ktei picture rui-ktei  ·  3Comentários

parallelthought picture parallelthought  ·  3Comentários

captbaritone picture captbaritone  ·  3Comentários

dmitry-zaets picture dmitry-zaets  ·  3Comentários