Использовать селектор и повторно выбирать, какой из них выгоден для производительности

#reactjs #redux #react-redux #reselect #redux-selector

#reactjs #сокращение #react-redux #повторный выбор #редукс-селектор

Вопрос:

Для запоминания / учета производительности используйте useSelector with ShallowEqual . Будут ли еще какие-то преимущества для оптимизации производительности с помощью опции «Reselect / createSelector»? Или оба варианта одинаковы?

Будет иметь данные в виде объектов массива JSON в большинстве селекторов.

Прежде чем писать новый селектор, хотелось бы рассмотреть преимущества производительности / запоминания.

Комментарии:

1. Повторный выбор полезен, потому что вы можете создавать селекторы, а запоминание может предотвратить запуск дорогостоящего кода селектора. Запоминание также может предотвратить ненужный повторный рендеринг. Что вам следует учитывать, так это поддерживаемый код, и с помощью reselect вы можете написать логику выбора один раз и повторно использовать ее, составляя селекторы. Вот пример того, как я использую reselect с react-redux.

2. Спасибо. Можно ли также добиться того же с помощью useSelector с shallowEqual (внутренне будет выполнять сравнение ссылок)? Или в повторном выборе было бы еще несколько преимуществ.

3. Даже если вы используете reselect только для запоминания (вы не должны этого делать), shallowEqual все равно не предотвратит создание новых объектов , даже если состояние не изменилось. Но вы должны использовать его, чтобы предотвратить повторение логики селектора. если ваш код имеет несколько state.someKey экземпляров, то при изменении состояния вам необходимо изменить свой код в нескольких местах. Это выглядит тривиально, но что, если ваши селекторы реализуют сложную бизнес-логику? Нравится const selectTotal = createSelector([selectPolicy,selectAge,selectPeriod,...],calculate)

4. значит, shallowEqual с useReducer не предотвратит повторный рендеринг?

Ответ №1:

 // Example
const selectAndCompute = (state) => {/*expensive computation*/};

const MyComponent = (props) => {
   const computedData = useSelector(selectAndCompute);
   return '...';
}
 

useSelector предотвратит повторную визуализацию MyComponent , если selectAndCompute функция вычисляет тот же результат, что и в прошлый раз, когда она была запущена (и она запускается каждый раз, когда что-либо в состоянии redux изменяется). Но для этого все равно требуется selectAndCompute запустить и вычислить некоторый результат. Это вычисление само по себе может быть дорогостоящим.

Итак, вы можете добавить reselect ‘s createSelector , чтобы предотвратить даже вычисления, выполняемые в selectAndCompute . Например, если selectAndCompute зависит только от той части состояния state.transactions , которую вы можете определить:

 const selectAndCompute = createSelector(
  [(state) => state.transactions], 
  (transactions) => {/*expensive computation*/}
);
 

Теперь, только если state.transactions изменилось, будет выполняться дорогостоящее вычисление, в противном selectAndCompute случае будет немедленно возвращено предыдущее значение. И useSelector , наконец, заблокирует повторный рендеринг, так же, как если reselect бы он не использовался.

Комментарии:

1. В документах useSelector указано, что The selector will be called with the entire Redux store state as its only argument. The selector will be run whenever the function component renders (unless its reference hasn't changed since a previous render of the component so that a cached result can be returned by the hook without re-running the selector) . Я что-то упускаю из этой формулировки? Разве это не означает, что селектор не будет запущен в случае shallowEqual(prevProps, newProps) , если он соответствует действительности?

2. @AlexandreGomes то, что вы процитировали, — это другая проблема. В нем обсуждается поведение, когда компонент повторно запускается по другим причинам, таким как изменение реквизитов компонента или его состояния (через useState). Выше я обсуждал проблему запуска useSelector при изменении хранилища redux.