How to memoize correctly using Redux reselect for O(1) complexity?
Tags: webdev, tutorial, javascript, react
Published: 2020-07-19 10:27:56

So we are used to writing redux selectors like this:

```javascript
// state is the universal redux state
// shop is one of the combined reducers
// O(1)
const selectShop = state => state.shop;

// collections is an object - O(1)
export const selectCollections = createSelector(
  [selectShop],
  shop => shop.collections
);

//return all collections as an array - O(N)
export const selectCollectionsForPreview = createSelector(
  [selectCollections],
  collections => Object.keys(collections).map(key => collections[key])
);

```

With this set up, for a component if you wish to retrieve the collections as an array you could do this:

```javascript

const mapStateToProps = createStructuredSelector({
  collections: selectCollectionsForPreview
})

export default connect(mapStateToProps)(MyComponent);

```

When the component is rendered for the first time, the **O(N)** operation will take place but from the second time (of course assuming the state hasn't mutated) it will just returned the collections array from the cache which makes it an **O(1)** operation.

Now think of a selector that should return collections as an array but filtered based upon a url parameter

Then you would have to create a function that generates a `createSelector` function that would look like this
which is an **O(N)** operation

```javascript
export const selectFilteredCollections = urlParam =>
  createSelector(
    [selectCollections],   // this returns the array as explained above and is memoized
    collections => collections.filter(coll => coll.type === urlParam)
  );

```

Now to use it you would do 

```javascript

const mapStateToProps = (state, ownProps) => ({
  collections: selectFilteredCollections(ownProps.match.url)
});

export default connect(mapStateToProps)(MyComponent);

```

The problem here is you are creating a new function that returns a `createSelector` function based on the url parameter each time the component renders.

So even if the url parameter remains the same for the second time of the call you are re creating a selector. So memoization didn't take place correctly.

In this situation, you will have to install `loadash` library

If using yarn:

`yarn add lodash.memoize`


If using npm:

`npm install lodash.memoize`


And to use it, we import our newly installed memoize helper function like so

```javascript
import memoize from 'lodash.memoize';
```

And just wrap our selectFilteredCollections function with memoize like so:

```javascript
export const selectFilteredCollections = memoize((urlParam) =>
  createSelector(
    [selectCollections],   // this returns the array as explained above and is memoized
    collections => collections.filter(coll => coll.type === urlParam)
  ));
```

Memoize does the same idea of memoization as reselect does for our selectors, except this time we're memoizing the return of our function which returns our selector:

```javascript
(urlParam) =>
  createSelector(
    [selectCollections],
    collections => collections.filter(coll => coll.type === urlParam)
 )
```

By wrapping this function is memoize, we're saying that whenever this function gets called and receives `urlParam`, I want to memoize the return of this function (in this case we return a selector). If this function gets called again with the same `urlParam` , don't rerun this function because we'll return the same value as last time, which we've memoized so just return the selector that's been stored.


Hope you had fun reading this !
Its my first post here :)

And oh ! did I forget to mention - you can learn more 
at the official website [Redux Reselect](https://github.com/reduxjs/reselect)

Also if you want to dive deep into loadash.memoize , checkout [this](https://dev.to/ccnokes/create-lodash-memoize-from-scratch-1p73) article that @CameronNokes wrote here on dev.to