Как Redux делает минимальный повторный рендеринг компонента? - PullRequest
0 голосов
/ 25 февраля 2020

Это сложный вопрос о React / Redux.

Кажется, я могу сделать каждый компонент моего приложения основанным на одном контексте (в качестве потребителей контекста) и использовать этот контекст в качестве единственного хранилища данных , Но затем, когда меняется контекст, каждый отдельный компонент моего приложения будет перерисован - и это нежелательно.

1) Когда я использую React и Redux вместо этого, чтобы каждый компонент перерисовывается как можно меньше, используя connect() и получая данные хранилища Redux как props, в React Developer Tool также есть Context.Provider, но я не вижу Context.Consumer - почему нет Context.Consumer - как компоненты могут получать данные, если нет потребителя контекста?

2) Redux каким-то образом просто добавляет так называемый «Connect» HO C (более высокий порядок) компонент), и добавьте props к нашим компонентам, чтобы наши компоненты повторно отображались при смене реквизита? Но я думал, что наши компоненты тоже находятся в этом «глобальном контексте Redux», поэтому, когда глобальный контекст Redux меняется, почему он не вызывает повторную визуализацию нашего компонента? Делается ли Connect потребителем контекста, а нашим компонентом - не потребителем контекста, а просто получает "реквизит"?

3) Я думал, что есть правило: когда state или props изменить, компонент и все поддерево будет повторно визуализировать. А как насчет контекста? Это немного отличается? То есть, когда контекст изменяется, то только компоненты, являющиеся потребителями контекста, будут перерисованы повторно, но если в этом поддереве есть потомки, которые не являются потребителями контекста, будет ли не перерисовываться? Иначе, как Redux может помочь свести к минимуму повторный рендеринг? Если контекст хранилища Redux изменяется, и все компоненты поддерева повторно визуализируются, то это то же самое, что и использование ванильного контекста, и пусть все компоненты являются потребителями.

4) Но, возможно, (3) выше не правильно ... потребители контекста и все поддерево перерисовываются ... просто так, Connect HO C может не быть потребителем контекста, но может получить состояние магазина Redux - на самом деле, нет Context.Consumer Что бы то ни было в инструменте React - как он работает?

5) Может быть, я нашел часть ответа: я продолжал видеть Memo и Context.Provider ... в React / Redux , Является ли Memo способом «остановить» повторный рендеринг от «перехода вниз по поддереву»? И тогда Context.Provider вместе с Memo походит на Connect HO C, чтобы предоставить компоненту props ... но как это Connect HO C получает состояние Redux, если это Memo? (как в React.memo() запомненном компоненте)? Если это сборка dev вместо производственной, то Memo - это ConnectFunction, а Context.Provider находится под ним, а затем наш «подключенный» компонент находится под ним.

6 Кстати, я не уверен, что это сделано с помощью shouldComponentUpdate()(): когда он возвращает false, все поддерево не перерисовывается, но если компонент наблюдает в хранилище Redux (используя store.subsribe()), и изменяет реквизиты для дочернего элемента (нашего подключенного компонента), а затем выглядит так, как Redux может работать внутри. В качестве альтернативы, , если компонент Connect просто наследует от PureComponent, тогда shouldComponentUpdate() просто поверхностно сравнивает состояние и поддерживает и возвращает false , если это просто изменение контекста. Это также приведет к тому, что целое поддерево не будет повторно отображаться. Я думаю, что это больше похоже на: если изменение контекста влияет на подключенный компонент внизу, тогда верните true для shouldComponentUpdate() и передайте соответствующий реквизит для подключенного компонента. В противном случае верните false и оставьте подключенный компонент в покое.

Повторная визуализация здесь не означает обновление фактического DOM. Это просто означает вызов render() компонентов класса или вызов компонента функции для получения виртуального дерева DOM, чтобы согласоваться с предыдущим виртуальным деревом DOM для поиска различий и, если таковые имеются, обновления фактического DOM.

1 Ответ

0 голосов
/ 25 февраля 2020

Примечание: Сам Redux не имеет привязок React, поэтому я предполагаю, что вы имеете в виду React Redux. Если нет, вам нужно будет переопределить любые оптимизации самостоятельно.

Кажется, я могу сделать каждый компонент моего приложения основанным на одном контексте (как потребители контекста), и использовать этот контекст как один и только хранилище данных.

Имейте в виду, что контексты - это не хранилища данных, а просто способы передачи данных дочерним компонентам без использования реквизита. Это скорее транспортный уровень.

Но тогда, когда меняется контекст, каждый отдельный компонент моего приложения будет перерисован - и это нежелательно.

Если вы используете необработанный контекст, вы должны перемещать потребителей контекста настолько глубоко, насколько вам это необходимо, чтобы ваши обновления контекста не вызывали столько ненужных повторных визуализаций (если это проблема в первую очередь, не забывайте преждевременно оптимизировать).

  1. В более новых версиях React Redux вместо Context.Consumer используется хук useContext, который не создает дополнительный элемент React ( source ). По сути, хук useContext сам является потребителем контекста, получая информацию о хранилище от провайдера контекста.
  2. По умолчанию connect автоматически запрещает повторные рендеринг при обновлении состояния Redux, если они не влияют на подключенный Реквизиты компонента или результат mapStateToProps.
  3. Обновление поставщика контекста заставит его потребителей перерисовывать, но не обязательно компоненты между ними или дочерние элементы пользователей-потребителей контекста.
  4. Это является потребителем контекста (см. ответ №1).
  5. memo - это новый способ предотвращения повторного рендеринга для компонентов функций, но если у вас есть компоненты класса, вы можете использовать вместо них PureComponent или shouldComponentUpdate , Это не альтернатива connect, это просто часть React, и вы можете использовать его с connect или более новым useSelector крючком, если хотите.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...