DEV Community

Cover image for How to stay DRY in redux state mapping when using reselect ?
Tilak Madichetti
Tilak Madichetti

Posted on

How to stay DRY in redux state mapping when using reselect ?

So we are probably used to mapping state to props this way where the values of props are basically selectors that are defined using createSelector function in reselect library
(which is mainly used for memoizing)


const mapStateToProps = state => ({
  itemCount: selectCartItemsCount(state),
  bagColor: selectCartColor(state),
  price: selectCartPrice(state)
});


export default connect(mapStateToProps)(MyApp);

Enter fullscreen mode Exit fullscreen mode

The problem with this approach is we are compelled to pass in state as argument in every select method even though we know
there is only 1 universal redux state

So to solve this we can

 import { createStructuredSelector } from 'reselect';
Enter fullscreen mode Exit fullscreen mode

This helps us reduce our code to follows:


const mapStateToProps = createStructuredSelector({
  itemCount: selectCartItemsCount,
  bagColor: selectCartColor,
  price: selectCartPrice
});


export default connect(mapStateToProps)(MyApp);

Enter fullscreen mode Exit fullscreen mode

And everything else stays intact and works just fine

NOW, you might ask yourself when should we NOT use createStructuredSelector ?

Well, there is one practical case that I encountered and that is when you want to dynamically generate a selector based on unknown props.

I'll explain - suppose MyApp is rendered this way:

<Route path='/mycart/:id' component={ MyApp } />
Enter fullscreen mode Exit fullscreen mode

In this case Route passes down the match object to MyApp and if you wish to generate a selector based on the match.params.id then in the mapStateToProps function you would need the match props as well apart from the redux based state(which is universal to the whole app btw)

So the solution would be:


const mapStateToProps = (state, ownProps) => ({
  itemCount: selectBasedOnUrl(ownProps.match.params.id)(state)
});

export default connect(mapStateToProps)(MyApp);

Enter fullscreen mode Exit fullscreen mode

Notice however that here, the itemCount is not memoized. If you want to learn how to memoize it, please check out my other post where I explain exactly that - its super important

Anyways I hope 🤞 you enjoyed what you read,
Don't forget to ❤️ it - I need encouragement to post !
And also don't hesitate to drop a comment below if you have anything to say.

Thanks for reading,
✌️

Top comments (0)