Examining the Benefits of Reselect.js by Recreating It

Netanel Basal
Netanel Basal
Published in
3 min readJun 17, 2020

--

Reselect is a library for optimizing Redux applications, that can prevent redundant renders, and improve the performance for combinations of multiple states or slices of states.

The motivation behind this library is found in its documentation, so we’ll not go into it here. If you’re unfamiliar with Reselect.js and what’s behind it, I recommend stopping here and reading the documentation before continuing.

In this article, we’ll recreate the createSelector function from scratch to understand how it works. Let’s get started.

First, we need to write a function that accepts an unknown number of arguments, and returns a function that takes a state object (in actual fact, it can also take props, so we’ll use the spread operator ).

Each argument apart from the last one should be a selector function. A selector function is just a function that takes a state object and returns a slice of it. The last argument is the result function — a function that’ll be called with the result of each of the selector functions:

First, we create a function named createSelector and use the spread operator to convert the arguments passed to the function to an array.

Next, we obtain a reference to the result function by using the pop() method. Then, we return a function that when called, loops over each selector function and calls it with the passed arguments. Finally, we call the result function with the resulting params.

Let’s try our function:

If we run the above code, we’ll see the log show up twice, indicating the result function was called twice, despite the fact that the state.shop.items property wasn’t modified between the calls. To make the createSelect more efficient, and prevent redundant calls, we’ll use memoization:

In computing, memoization or memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again

Let’s create a memoize function with Javascript:

We create a function, that takes a function and returns a new one (i.e., a higher-order function). We leverage JS closures to persist the last arguments used and last result returned. We only invoke the original function if the previous and current arguments aren’t identical.

The areArgumentsShallowlyEqual function is a simple function, that compares the previous and current arguments by reference:

Now let’s use the memoize function in our createSelector function:

Let’s explain why we used memoization twice. The first instance is where we memoize the result function, to prevent the issue we discussed before. If we call our function multiple times and the result of each of the selector functions wasn’t changed by reference, we don’t want to rerun the result function:

Now we’ll see the log show up only once, because the state.shop.items property didn’t change.

In the second instance, we use memoization for the function we return from our createSelector() call. The reason for that is, if we call the function multiple times with the same state, we want to avoid rerunning the inner function, which calculates each of the selector’s results:

When we run the above code, we’ll only see the log once in our console. You can play with the code here.

🚀 In Case You Missed It

Here are a few of my open source projects:

  • Akita: State Management Tailored-Made for JS Applications
  • Spectator: A Powerful Tool to Simplify Your Angular Tests
  • Transloco: The Internationalization library Angular
  • Forms Manger: The Foundation for Proper Form Management in Angular
  • Cashew: A flexible and straightforward library that caches HTTP requests
  • Error-tailor — Seamless form errors for Angular applications

Follow me on Medium or Twitter to read more about Angular, Akita and JS!

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.