9

For memoization/performance consideration, using useSelector with ShallowEqual. Will there be some more benefits for performance optimization using "Reselect/createSelector" option ? Or both the options are same ?

Will have the data as JSON array objects at most of the selectors.

Before writing new selector , would like to consider performance/memoization benefits.

dsi
  • 3,199
  • 12
  • 59
  • 102
  • 2
    Reselect is useful because you can compose selectors and the memoization can prevent expensive selector code from running. The memoization can also prevent needless re renders. What you should consider is maintainable code and with reselect you can write selector logic once and re use it by composing selectors. [Here](https://github.com/amsterdamharu/selectors) is an example of how I use reselect with react-redux. – HMR Mar 01 '21 at 19:55
  • Thanks. Can it be also achieve same with, useSelector with ShallowEqual (internally would do reference comparision) ? Or there would be some more benefits in ReSelect. – dsi Mar 01 '21 at 20:15
  • 1
    Even if you only use reselect for memoization (you shouldn't) then shallowEqual still won't prevent [generating new objects](https://github.com/amsterdamharu/selectors/blob/master/src/selectors.js#L16-L19) even if state didn't change. But you should use it to prevent repeating selector logic. if you code has multiple `state.someKey` instances then you need to change your code in multiple places when you change the state. This looks trivial but what if your selectors implement complex business logic? Like `const selectTotal = createSelector([selectPolicy,selectAge,selectPeriod,...],calculate)` – HMR Mar 01 '21 at 21:09
  • means, shallowEqual with useReducer will not prevent re-rendering ? – dsi Mar 02 '21 at 01:29

1 Answers1

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

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

useSelector will prevent re-render of MyComponent if the selectAndCompute function computes the same result as last time it got triggered (and it gets triggered every time anything in redux state changes). But, this still requires selectAndCompute to run and compute some result. This computation in itself might be expensive.

So, you can add reselect's createSelector to prevent even the computation done in the selectAndCompute. For example if selectAndCompute depends only on the part of the state state.transactions you can define:

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

Now, only if state.transactions has changed the expensive computation will run, otherwise selectAndCompute will immediately return the previous value. And finally useSelector will then block the re-render, same as it would if reselect was not used.

croraf
  • 4,332
  • 2
  • 31
  • 50
  • [useSelector](https://react-redux.js.org/api/hooks#useselector) docs state that `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)`. Am I missing something from this phrasing? Doesn't it mean that the selector won't be run in case `shallowEqual(prevProps, newProps)` is truthy? – gomes Sep 23 '21 at 15:41
  • 2
    @AlexandreGomes what you quoted is a different issue. It discusses the behavior when the component rerenders due to other reasons, like component's props being changed, or its state (through useState). Above I discussed the issue of useSelector being triggered from the redux store change. – croraf Sep 24 '21 at 21:18