Como otimizar pequenas atualizações nos objetos do componente aninhado no React + Redux?
Código de exemplo:https://github.com/d6u/example-redux-update-nested-props/blob/master/one-connect/index.js
Ver demonstração ao vivo:http://d6u.github.io/example-redux-update-nested-props/one-connect.html
Como otimizar pequenas atualizações para adereços do componente aninhado?Eu tenho componentes acima, Repo e RepoList. Quero atualizar a tag do primeiro repo (Linha 14) Então eu enviei umUPDATE_TAG
açao. Antes de implementarshouldComponentUpdate
, o envio demora cerca de 200 ms, o que é esperado, pois estamos perdendo muito tempo<Repo/>
s que não mudaram.
Depois de adicionadoshouldComponentUpdate
, a expedição leva cerca de 30ms. Após a criação do React.js, as atualizações custam apenas cerca de 17ms. Isso é muito melhor, mas a exibição da linha do tempo no console do desenvolvedor do Chrome ainda indica um quadro irregular (mais de 16.6ms).
Imagine se tivermos muitas atualizações como essa ou<Repo/>
é mais complicado que o atual, não conseguiremos manter 60fps.
Minha pergunta é: para atualizações tão pequenas nos acessórios de um componente aninhado, existe uma maneira mais eficiente e canônica de atualizar o conteúdo? Ainda posso usar o Redux?
Eu tenho uma solução substituindo todos ostags
com um redutor interno observável. Algo como
// inside reducer when handling UPDATE_TAG action
// repos[0].tags of state is already replaced with a Rx.BehaviorSubject
get('repos[0].tags', state).onNext([{
id: 213,
text: 'Node.js'
}]);
Então, assino seus valores dentro do componente Repo usandohttps://github.com/jayphelps/react-observable-subscribe. Isso funcionou muito bem. Cada envio custa apenas 5ms, mesmo com a compilação de desenvolvimento do React.js. Mas sinto que isso é um anti-padrão no Redux.
Atualização 1Eu segui a recomendação na resposta de Dan Abramov enormalizou meu estado ecomponentes de conexão atualizados
A nova forma de estado é:
{
repoIds: ['1', '2', '3', ...],
reposById: {
'1': {...},
'2': {...}
}
}
Eu adicioneiconsole.time
por aíReactDOM.render
tempoa renderização inicial.
No entanto, o desempenho está pior do que antes (renderização inicial e atualização). (Fonte:https://github.com/d6u/example-redux-update-nested-props/blob/master/repo-connect/index.js, Demonstração ao vivo:http://d6u.github.io/example-redux-update-nested-props/repo-connect.html)
// With dev build
INITIAL: 520.208ms
DISPATCH: 40.782ms
// With prod build
INITIAL: 138.872ms
DISPATCH: 23.054ms
Eu acho que conectar em todos os<Repo/>
tem muita sobrecarga.
Com base na resposta atualizada de Dan, precisamos retornarconnect
émapStateToProps
argumentos retornam uma função. Você pode conferir a resposta de Dan. Eu também atualizeias demos.
Abaixo, o desempenho é muito melhor no meu computador. E por diversão, também adicionei o efeito colateral na abordagem de redutor que falei (fonte, demonstração) (sério, não use, é apenas para experimentos)
// in prod build (not average, very small sample)
// one connect at root
INITIAL: 83.789ms
DISPATCH: 17.332ms
// connect at every <Repo/>
INITIAL: 126.557ms
DISPATCH: 22.573ms
// connect at every <Repo/> with memorization
INITIAL: 125.115ms
DISPATCH: 9.784ms
// observables + side effect in reducers (don't use!)
INITIAL: 163.923ms
DISPATCH: 4.383ms
Atualização 3Acabei de adicionarexemplo react-virtualized com base em "conecte-se a cada memorização"
INITIAL: 31.878ms
DISPATCH: 4.549ms