Как оптимизировать небольшие обновления реквизита вложенного компонента в React + Redux?
Пример кода:https://github.com/d6u/example-redux-update-nested-props/blob/master/one-connect/index.js
Посмотреть демо:http://d6u.github.io/example-redux-update-nested-props/one-connect.html
Как оптимизировать небольшие обновления реквизита вложенного компонента?У меня есть вышеуказанные компоненты, Repo и RepoList. Я хочу обновить тег первого репо (Линия 14). Поэтому я отправилUPDATE_TAG
действие. До того как я реализовалshouldComponentUpdate
отправка занимает около 200 мсек, что ожидается, так как мы тратим много времени<Repo/>
которые не изменились.
После добавленияshouldComponentUpdate
Доставка занимает около 30 мс. После производственной сборки React.js обновления стоят всего около 17 мс. Это намного лучше, но временная шкала в консоли разработчика Chrome по-прежнему указывает на джанк-фрейм (более 16.6 мс)
Представьте, если у нас будет много таких обновлений или<Repo/>
более сложный, чем текущий, мы не сможем поддерживать 60fps.
Мой вопрос заключается в том, что для таких небольших обновлений реквизита вложенного компонента существует ли более эффективный и канонический способ обновления содержимого? Могу ли я использовать Redux?
Я получил решение, заменив каждыйtags
с наблюдаемым внутри редуктором. Что-то вроде
// 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'
}]);
Затем я подписываюсь на их значения внутри компонента Repo, используяhttps://github.com/jayphelps/react-observable-subscribe, Это сработало отлично. Каждая отправка стоит всего 5 мс даже при разработке сборки React.js. Но я чувствую, что это анти-паттерн в Redux.
Обновление 1Я последовал рекомендации в ответе Дана Абрамова инормализовал мое состояние а такжеобновлены компоненты подключения
Новая государственная форма:
{
repoIds: ['1', '2', '3', ...],
reposById: {
'1': {...},
'2': {...}
}
}
я добавилconsole.time
вокругReactDOM.render
ко времениначальный рендеринг.
Тем не менее, производительность хуже, чем раньше (как начальный рендеринг, так и обновление). (Источник:https://github.com/d6u/example-redux-update-nested-props/blob/master/repo-connect/index.js, Живая демонстрация: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
Я думаю подключиться на каждом<Repo/>
имеет много накладных расходов.
Основываясь на обновленном ответе Дэна, мы должны вернутьсяconnect
«smapStateToProps
аргументы возвращают функцию вместо этого. Вы можете проверить ответ Дэна. Я тоже обновилдемки.
Ниже производительность намного лучше на моем компьютере. И просто для удовольствия, я также добавил побочный эффект в подходе редуктора, о котором я говорил (источник, демонстрация) (серьезно не используйте его, это только для эксперимента).
// 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
Обновление 3Только что добавленреактивно-виртуализированный пример основанный на «подключиться к каждому с запоминанием»
INITIAL: 31.878ms
DISPATCH: 4.549ms