5

Selectors are efficient. A selector is not recomputed unless one of its arguments changes.

I'm trying to debug a selector that is being called more often than expected. Is there a way to log why a particular selector was recomputed (i. e. which argument changed)?

Example:

export const totalSelector = createSelector(
  [subtotalSelector, taxSelector]
  (subtotal, tax) => ({ total: someExpensiveCalculation(subtotal, tax) })
)

Now let's say that the return value of totalSelector is supplied to some component as a result prop via mapStateToProps. why-did-you-render reports unnecessary render due to changing reference (not value) of result. Therefore I know totalSelector must have been recomputed and we know from the docs that it only happens when of its inputs change (subtotal or tax in the example). How can I tell whether it was subtotal that triggered a change or tax or both?

For the purpose of this explanation let's assume both subtotal and tax are objects, so they are passed by reference.

asliwinski
  • 1,662
  • 3
  • 21
  • 38

3 Answers3

3

Here's a simple drop-in replacement for createSelector which will log the first changed param value:

const createDebugSelector = createSelectorCreator(defaultMemoize, {
  equalityCheck: (previousVal, currentVal) => {
    const rv = currentVal === previousVal;
    if (!rv) console.log('Selector param value changed', currentVal);
    return rv;
  },
});
Ilya Boyandin
  • 3,069
  • 25
  • 23
0

One thing that helped me in my situation is to put a breakpoint at this line so that you can clearly see the argument that is causing the recomputation.

Kipr
  • 806
  • 10
  • 13
-1

You should check this tool out: https://github.com/welldone-software/why-did-you-render

Put it on the component (the one wrapped in connect) and it will tell you which props are deep equal but not shallow equal.

Bill Johnston
  • 1,160
  • 1
  • 14
  • 31
  • I'm using this tool, on the component level it does a great job. So I know that a particular selector got recomputed. What I want to know is why it was recomputed. – asliwinski Dec 17 '19 at 14:41
  • His blog posts actually have great descriptions of the problems and potential fixes: https://medium.com/welldone-software/why-did-you-render-mr-big-pure-react-component-part-2-common-fixing-scenarios-667bfdec2e0f. If you post the code of your selector I may be able to help more – Bill Johnston Dec 17 '19 at 15:00
  • example provided, it's not really about the selector implementation though. – asliwinski Dec 17 '19 at 18:08
  • Maybe you can do something like this to debug: https://codesandbox.io/s/clever-faraday-jw99j. Create a custom createSelector where you log out the values and if they are equal or not – Bill Johnston Dec 18 '19 at 20:41