Search code examples
javascriptreactjsreselectreact-boilerplate

Why does React-boilerplate selector.js export methods which call createSelector instead of exporting selector directly?


I'm using react-boilerplate which in turn uses reselect. I've noticed their use of reselect is a bit different then how reselect is documented. In fact I would have thought that it was defeating the advantage of reselect if not for the fact that I'm pretty sure the developers of the framework know what they are doing better then me and that there is a reason for their approach. I'm trying to understand that reason better so I know how to move forward with adding selectors to boilerplate. My confusion is react-boilerplate's exporting methods which call createSelector, instead of exporting an already created selector.

Reselect's documentation has a selectors file which exports already created selectors, and then they call these selectors directly in mapStateToProps. So something like this:

selector.js:

export const basicSelector = (state) => (state.basic.data);

export const fooSelector = createSelector(basicSelector, (state) => (state.get(foo));

export const barSelector = createSelector(basicSelector, (state) => (state.get(foo)));

in component:

function mapStateToProps(state) => ({
    foo: fooSelector(state),
    bar: barSelector(state),
});

However, react-boilerplate's selector instead exports methods which call createSelector, instead of exporting a created selector directly. So something like this:

selector.js:

export const basicSelector = (state) => (state.basic.data);

export const fooSelector = () => {
  return createSelector(basicSelector, (state) => (state.get(foo)));
}

export const barSelector = () => {
  return createSelector(basicSelector, (state) => (state.get(foo)));
}

in component:

const mapStateToProps = createStructuredSelector({
  foo: fooSelector(),
  bar: barSelector(),
});

What is the motivation for calling these dummy methods to create the selector? I would have thought that react-boilerplates approach would mean that if I reuse a selector in different components that each component would have a different instance of the selector; which in turn would mean that each component would have to calculate the result of the selector when state changes rather then it being done once ultimately resulting in redundant calculations.

As I said I suspect i'm missing something, as I doubt a widely used framework would simply fail to use reselect correctly. Could someone explain to me the benefit, and why/if I should maintain react-boilerplate's approach vs doing it the way reselect documentation shows?


Solution

  • What you describe in your second is example is not exactly a selector but a selector factory. It creates and returns a new selector.

    Sometimes sharing selectors among different components is tricky, because each component might call the selector with different parameters invalidating reselect cache on each call.

    A selector factory avoid this problem by assigning a new different selector to each connected component.

    By convention selector factories names usually begin with makelike makeSelectBar or makeGetBar.