redux mapStateToProps optimization
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 asmapStateToProps()
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.