Передача объекта из Redux из React вызывает ненужные рендеры? - PullRequest
2 голосов
/ 31 октября 2019

Я отлаживаю проблему с производительностью в моем приложении. Мой компонент верхнего уровня App выполняет рендеринг каждый раз, когда изменяется состояние Redux, даже если его props (из Redux) имеют одинаковые значения.

Передано 2 реквизита от Redux, один - строка, а другой - объект.

export default connect(state => ({
  name: state.name, // This is a string
  address: state.address // This is an object
}))(App);

Это address (объект), который вызывает проблему. Правильно ли я думаю, что это потому, что функция Redux connect выполняет поверхностное сравнение и думает, что address изменился, поскольку это новый объект, даже если думал, что значения не изменились?

Предполагая, что этоправильно, я считаю, что решение заключается в том, чтобы либо запомнить address, например, с помощью модуля повторного выбора, либо использовать shouldComponentUpdate (что мне кажется более грязным). Я прав, что это 2 нормальных решения?

Ответы [ 3 ]

1 голос
/ 31 октября 2019

use shouldComponentUpdate (что мне кажется более грязным)

На самом деле React Redux уже выполняет внутренний shouldComponentUpdate и выполняет только поверхностную проверку на равенство.

Таким образом, бесполезно дублировать его в вашем компоненте.

либо запомните адрес, например, с помощью повторного выбора

Это должно быть вашим решением, поскольку оно гарантирует, что connectпропустит повторный рендеринг, если значения совпадают.

0 голосов
/ 31 октября 2019

Я согласен с вашей оценкой, connect действительно делает поверхностное сравнение, и если объект address является новым, он будет перерисован.

Я бы посоветовал не использовать shouldComponentUpdate для решения этой проблемы. так как это может легко привести к ошибкам, когда ваше приложение не обновляется при необходимости.

reselect - хороший вариант для общего случая, но в вашем случае может быть другой вариант - вы можете извлечь из address объект значения в mapStateToProps:

export default connect(state => ({
  name: state.name, // This is a string
  city: state.address.city, // This is a string now
  street: state.address.street, 
  // etc. 
}))(App);

Если вам нужны все значения, вы можете просто распространить объект address:

export default connect(state => ({
  name: state.name, // This is a string
  ...state.address,
}))(App);
0 голосов
/ 31 октября 2019

Насколько я понимаю, на самом деле это всегда возвращает новый объект

export default connect(state => ({
 name: state.name, // This is a string
 address: state.address // This is an object
}))(App);

Скажем, ваше состояние избыточности обновляет некоторое значение, но не имя или адрес, избыточность будет вызывать все mapDispatchToProps вваше приложение и оно вернуло бы новый объект

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

Надеюсь, что это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...