redux mapStateToProps optimization

Cvetanov Goce
3 min readMar 20, 2017

--

First of all, what is redux?

Redux is an open source implementation (aren’t they all?) of the flux architecture suggested by Facebook as a compliant standard for working with data in large React applications.

Created by Dan Abramov, who now works on the create-react-app (by the way, the best generator for scaffolding production ready React apps), it contains everything suggested from the flux pattern in an easy-to-use manner and also contains some JS tricks (like defining an empty function and later checking it’s name to determine if the code has been minified) which is not the main content of this article.

Redux itself is a very simple implementation and there was an interesting article which points out that the patterns used in the implementation of redux can be done in as few as 12 lines of code. This is of course without all of the optimization redux offers and the sanity checks it provides for better developer experience.

For using redux in React applications, the react-redux module is available in npm and it provides a very simple connect function which (you guessed it) connects your component to the redux store.

The main content of this article is how to obtain a minor optimization on connected components which use their own props for querying the redux state.

Let’s say that we have a blog application and we want a particular component MyBlogs to display all the blogs for the logged in user. We have the logged in user somewhere else in our application and we pass it down to the MyBlogs component as a prop. Now we want to display all of the blogs whose author is the logged in user. Redux’s mapStateToProps offers the props of the component as a second argument. We can use them to query the redux state and return a slice of it depending on some prop of the component. This will look something like this:

function mapStateToProps(state, ownProps) {
return {
blogs: state.blogs.filter(blog => blog.author === ownProps.user)
};
}
export default connect(mapStateToProps)(MyBlogs);

We create a mapStateToProps implementation which uses the user from the component’s own props and returns all of the blogs from the redux state for that particular user.

Fortunately for us, the guys contributing to redux and react-redux are great, open to new ideas and always making contribution to the library’s performance and documentation and therefore, they offer us an option to perform a minimal optimization here.

mapStateToProps can now return a function instead of an object.

Note: in advanced scenarios where you need more control over the rendering performance, mapStateToProps() can also return a function. In this case, that function will be used as mapStateToProps() for a particular component instance. This allows you to do per-instance memoization. [from the official docs]

If redux receives an implementation which returns a function it performs a closure for wrapping the own props of the component and therefore bypasses the invocation of the mapStateToProps every time the component changes it’s props received from the parent component. It creates a so called purePropsSelector. How this is done can be seen here.

We can now rework our implementation of the MyBlogs component in the following way and achieve a minor performance boost.

function mapStateToPropsFactory(initialState, ownProps) {
// a closure for ownProps is created
// this factory is not invoked everytime the component
// changes it's props
return function mapStateToProps(state) {
return {
blogs:
state.blogs.filter(blog => blog.author === ownProps.user)
};
};
}
export default connect(mapStateToPropsFactory)(MyBlogs);

TL;DR;

When using the component’s own props inside mapStateToProps, wrap the mapStateToProps function with a mapStateToPropsFactory which will return the function itself instead of the object directly and redux will not invoke your mapStateToPropsFactory for every parent prop changes.

Thanks to my mentor Oliver Lazoroski for pointing this out to me and I will share his TL;DR; remark on this:

Think of it like this, if redux receives a mapStateToProps which has ownProps as second argument and it returns an object, it switches off every optimization it makes for your connected component.

This was my first of many articles on medium and I hope you will find it useful.

--

--