Selectors and derived data with Redux

In Redux, deciding what kind of data we put in the store requires good planning to make sure our application will scale effectively, and future updates won’t break the app. With this in mind, it’s considered good advice to keep the design of the state tree as minimal and normalized as possible for several reasons, including reusability, easy updates, and removing data coupling between view components and the store. By having a normalized state tree, we can also reduce the number of actions, leaving the heavy work of computing data to an external player, selectors.

Selectors complement Redux by allowing us to create query functions that derive computed data from our state tree. The resulting data structure is ideally tailored to fit our view component, which then receives it in the shape of props.

computed-data

Similar to how in SQL you can build SELECT queries that grab data from different parts of your database, like joining or filtering, selectors are functions that perform transformations with the state, such as filtering, mapping, sorting, concatenations, etc. This is why leaning towards storing minimal data in our state tree is important, we could now leave the data transformation to selectors and decouple this functionality.

To put things into perspective, the most basic version of a selector would be getting something from the store without performing any transformations on it:

That is a very simple selector, and you can see that you don’t need a library to query something that simple. As a matter of fact, you can build a more complex selector and not use any third party library.

Let’s look at a selector that does actually derive data by making a transformation. This next example shows how to create a selector that filter phones by country and append a logo of the phone maker to each one of them, given that our state structure looks like:

The following part defines a selector that gets phones by country, and includes the part where Redux connects computed data to the props:

Reselect: Redux’s own selector library

The last example solves the problem of separating the calculated data by isolating this functionality in a selector, which grabs some data from the state tree and filters it to create new derived data. However, we know that in Redux every time the state changes, it will try to map state to props again, which will try to re-execute this selector function, and if the state that changes is not related to this selector, then we’ll be executing a function that returns the same data over and over, creating a performance burden. Granted, this example is small, but if we had a large collection, or even more complex transformations, this operation would be more expensive and would lead to poor performance. This is why Reselect exists.

Reselect is a selector library for Redux that solves this exact problem by memoizing queries/selectors based on the passed state arguments this selector depends on. In other words, If the data we want to derive is based on state data that hasn’t changed, then reselect will just reuse the cached derived data, causing less unnecessary renders.

This is how the last example would look by adding Reselect’s createSelector function:

redux selectors

Reusability

Since selectors are just functions that rely on state, you can use them across your components with the intention of keeping your actions clean and keeping your derived data in an easy to find location. Also, your actions are less coupled to the state. If your state structure changes for some reason, you don’t have to update every single action where you relied on this structure. You know you can just go to your selectors file to find what you’re looking for.

When you create a reusable selector, you must make sure that each time this selector is used, you have to create a new instance of the createSelector function. This is necessary to ensure that each part of our application that imports this selector has a unique reference to this function, avoiding referencing the previous memoization.

In the following code notice how makePhonesByCountry will export a function to createSelector:

Assuming we’re using Redux thunk pass in the state, here’s how we would use a selector inside an action:

However, if we wanted to use this selector inside a mapStateToProps using connect(). We must also make sure that each time an instance of our container is created, it has reference to its own copy of the selector. This would be done following the same idea, in this case, we need to return a function that creates mapStateToProps, so we can have a unique instance.

Compose them

With reselect you can also feed selectors as input arguments to other selectors. This promotes reusability and you can leverage your already cached data.

Finally, you might not need reselect

In certain cases, you might not need to memoize data with reselect. If you don’t have any logic in your selector function, and you just want to return a reference to the state tree (like the first example). Then there’s really no point in using the reselect to memoize, since Redux’s connect() will avoid re-renders and calls to mapStateToProps if the state object in question is equal to the last one. Note that by default connect() does a shallow comparison. For more on this topic check connect() documentation .

Share
FILE UNDER: