Debugging Microservices & Distributed Systems
4 min read

Boost React + Redux Performance with Reselect

Selectors are a powerful tool to optimize state selection and enhance performance in your React and Redux apps.

When working with React and Redux, efficient state selection is key for high performance. Reselect is a library that helps create memoized selectors, which optimize state selection by reducing unnecessary re-renders.

Selectors are functions that pick a slice of state from the Redux store. They help separate your state logic from your components, keeping things cleaner and more maintainable.

Here’s a basic example of a Redux state:

const initialState = {
data: [
{ name: "Milton", type: "cat", age: 4 },
{ name: "Sammy", type: "dog", age: 2 },
{ name: "Joseph", type: "turtle", age: 34 },
{ name: "Simon", type: "dog", age: 8 }
]
};

Without selectors, you might directly filter the state inside a component, which could cause performance issues when repeated multiple times.

const dogs = useSelector(state =>
state.data.filter(animal => animal.type === 'dog')
);

Looks fine, right? The problem is, every time your component re-renders, this filter operation runs again. As your app grows, this can make things slow and difficult to manage. This is where Reselect shines.

Installing Reselect

You can install Reselect with just one command:

Terminal window
yarn add reselect

Once installed, you can start using it to create memoized selectors that will only recalculate when the input state changes.

Building Your First Selector

Reselect provides the createSelector function, which lets you build memoized selectors easily. The basic idea is simple: the last argument is a function that selects data, while the previous arguments are input selectors.

Let’s create a selector to get all pets and another one to filter out the dogs.

import { createSelector } from 'reselect';
const selectAllPets = state => state.data;
export const selectAllDogs = createSelector(
selectAllPets,
allPets => allPets.filter(animal => animal.type === 'dog')
);

Here, selectAllPets is the input selector, and the second argument is the filter function. The result will only be recalculated if the list of pets changes.

Using the Selector in Your Component

Now that we have our memoized selector, let’s use it in a React component.

import { useSelector } from 'react-redux';
import { selectAllDogs } from './selectors';
const PetsContainer = () => {
const dogs = useSelector(selectAllDogs);
return (
<div>
<h1>Dogs</h1>
<ul>
{dogs.map(dog => (
<li key={dog.name}>{dog.name} - {dog.age} years old</li>
))}
</ul>
</div>
);
};

With this approach, you are no longer recalculating the list of dogs on every render. The selector is memoized, meaning it remembers the result and only recalculates when necessary, improving performance.

Why Reselect is Powerful

  • Memoization: Selectors don’t recalculate unless one of their inputs changes. This cuts down on unnecessary computations, improving performance.
  • Composability: You can build selectors on top of other selectors. This makes your state logic cleaner and easier to manage.
  • Efficiency: By keeping your components focused on rendering and moving logic to selectors, you reduce component complexity and make your app more maintainable.

Combining Selectors

You can also compose selectors to pick different parts of your state. Let’s say we want to select both dogs and cats. We can create separate selectors and combine them:

export const selectAllCats = createSelector(
selectAllPets,
allPets => allPets.filter(animal => animal.type === 'cat')
);
export const selectAllDogsAndCats = createSelector(
selectAllDogs,
selectAllCats,
(dogs, cats) => [...dogs, ...cats]
);

Here, selectAllDogsAndCats takes the results of the selectAllDogs and selectAllCats selectors and combines them into a single array. You can then use it in your component just like before:

const PetsContainer = () => {
const dogsAndCats = useSelector(selectAllDogsAndCats);
return (
<div>
<h1>Dogs and Cats</h1>
<ul>
{dogsAndCats.map(pet => (
<li key={pet.name}>{pet.name} - {pet.age} years old</li>
))}
</ul>
</div>
);
};

Memoization in Action

Reselect uses memoization to optimize performance. Once a selector calculates a result, it stores the result in memory. If the inputs don’t change, it returns the same result without recalculating.

Let’s say you update the state with a new pet:

dispatch({
type: 'ADD_PET',
payload: { name: "Charlie", type: "dog", age: 5 }
});

Only then will the selectAllDogs selector recalculate the list of dogs, because the state has changed. If nothing changes, it returns the memoized result, keeping your app snappy.

Selectors are a critical part of optimizing your React + Redux application, and Reselect makes it incredibly easy to create memoized selectors that improve performance. By moving state selection logic out of components and into memoized selectors, you reduce unnecessary recalculations, making your app faster and more maintainable.


Related Articles

If you enjoyed this article, you might find these related pieces interesting as well.

Recommended Engineering Resources

Here are engineering resources I've personally vetted and use. They focus on skills you'll actually need to build and scale real projects - the kind of experience that gets you hired or promoted.

Imagine where you would be in two years if you actually took the time to learn every day. A little effort consistently adds up, shaping your skills, opening doors, and building the career you envision. Start now, and future you will thank you.


This article was originally published on https://www.trevorlasn.com/blog/increase-react-redux-application-performance-with-reselect-library. It was written by a human and polished using grammar tools for clarity.

Interested in a partnership? Shoot me an email at hi [at] trevorlasn.com with all relevant information.