🥢Selector in Redux
Tags: redux, react, javascript
Published: 2021-01-28 08:46:19

> A “selector” is simply a function that accepts Redux state as an argument and returns data that is derived from that state.

> A selector is a small function you write that can take the entire Redux state, and pick out a value from it.

You know how `mapStateToProps` works? How it takes the entire state and picks out values? Selectors basically do that. And, bonus, they improve performance too, by caching the values until state changes. Well – they can improve performance.

## Why should you use a selector?

It is a best practice to keep your Redux store state minimal and derive data from the state as needed. Selectors help with that. They can compute derived data, allowing Redux to store the minimal possible state. Selectors are also very efficient. A selector is not recomputed unless one of its arguments changes.

## Some examples of Selectors:

Basic :

```jsx
selectUsers = state => state.users;
```

Slightly Complex using ID:

```jsx
selectUserIds = state => state.users.map(user => user.id);
```

More Complex:

```jsx
selectUserIdsOfName = (state, name) => state.users.filter(user => user.name === name);
```

## An Example

Redux gives you a store where you can put state. In a larger app, that state is usually an object, where each key of the object is managed by a separate reducer.

```jsx
{
  currentUser: {
    token,
    userId,
    username
  },
  shoppingCart: {
    itemIds,
    loading,
    error
  },
  products: {
    itemsById,
    loading,
    error
  }
}
```

### First, without a selector

- When it comes time to get data out of the Redux state and into your React components, you’ll write a `mapStateToProps` function that takes the entire state and cherry-picks the parts you need.
- Let’s say you want to show the items in the shopping cart. To do that, you need the items. Buuut the shoppingCart doesn’t have items. It only has item IDs. You have to take each ID and look it up in the products.items array. Here’s how you might do that:

```jsx
function mapStateToProps(state) {
  return {
    items: state.shoppingCart.itemIds.map(id => 
      state.products.itemsById[id]
    )
  }
}
```

### Changing the state shape breaks `mapStateToProps`

Now – what happens if you decide “You know… `shoppingCart` should really be a property of the `currentUser` instead of a standalone thing.” And then they reorganize the state to look like this:

```jsx
currentUser: {
    token,
    userId,
    username,
    shoppingCart: {
      itemIds,
      loading,
      error
    },
  },
  products: {
    itemsById,
    loading,
    error
  }
}
```

- Well, now your previous `mapStateToProps` function is broken. It refers to `state.shoppingCart` which is now held at `state.currentUser.shoppingCart`.
- If you had a bunch of places in your app that referred to `state.shoppingCart`, it’ll be a pain to update all of them. Fear or avoidance of that annoying update process might even prevent you from reorganizing the state when you know you should.

If only we had a way to centralize the knowledge of the shape of the state… some kind of *function* we could call that knew how to find the data we wanted…

Well, that’s exactly what a selector is for :)

### Refactor: Write a simple selector

Let’s rewrite the broken `mapStateToProps` and pull out the state access into a selector.

```jsx
// put this in some global-ish place,
// like selectors.js,
// and import it when you need to access this bit of state
function selectShoppingCartItems(state) {
  return state.currentUser.shoppingCart.itemIds.map(id => 
    state.products.itemsById[id]
  );
}

function mapStateToProps(state) {
  return {
    items: selectShoppingCartItems(state)
  }
}
```

Next time the state shape changes, you can update that one selector and you’re done.

## Memoization

- The use of selectors in your application can also provide performance optimizations. Let’s say you have a component that needs to run an intensive sorting operation on the store’s state in order to get the data it needs. If you were to perform the operation in your mapStateToProps() function, without the use of a selector, the operation would run ***every*** time a dispatched action caused the state to update!
- It would be great if we could only run the expensive sorting operation only when the data we are running the operation on changes. This is where the concept of memoization comes to the rescue.
- Memoization is a form of caching. It involves tracking inputs to a function, and storing the inputs and the results for later reference. If a function is called with the same inputs as before, the function can skip doing the actual work, and return the same result it generated the last time it received those input values.

###Conclusion
A selector is a function that accepts Redux state as an argument and returns data that is derived from that state. Selectors can provide performance optimizations to your application and can also help you encapsulate your global state tree.