Redux Selectors: Driving Data With Redux Selectors

This article will discuss various Redux selectors and how to use them in detail. But we should certainly know what selectors are.

Selectors are a function that holds the Redux state from the Redux store as an argument and returns some value to the component. They are frequently used in mapStateToProps functions to give data to the elements. For instance, this is what a selector looks like:

 cconst getProducts = ({ products }) => products; 

As we now know what a selector is, let us discuss Redux selectors and how to use them in detail. 

See Also: Exploring Query Strings (Search Params) In React Router 

Are Selectors helpful?

It is always advised to keep our Redux store nominal and then drive data from the state when you want. This is where Redux selectors play a vital role and are helpful.

redux selectors

They also calculate the data and allow the Redux to store the nominal feasible state. Furthermore, they are also efficient; you don’t need to figure again except if the argument changes.

A few examples:

We now know certainly what selectors are. Let’s discuss some examples in detail to understand selectors better. The first example is a selector function used for getting a list of users from Redux:

selectors example

 selectUsers = state => state.users; 

Furthermore, we can make it trickier by trying to get user IDs. For instance:

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

We can also make this code more advanced by selecting users with a specific name. For instance:

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

See Also: Passing Functions As Props In React: Full Guide

First, let us do without a selector

For understanding without a selector in detail, we should first have an example layout: 


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

 

In this example, it keeps the information of the user that logged in, products available in your shop, and also the items selected for the shopping cart. Another key point is that an ID adds the items selected for a shopping cart in the shoppingCart.itemIds array.

Now, you can use mapStateToProps to hand-pick the IDs for the entire state. Let us assume you want to see the items added to the shopping cart. To clarify, you must look into shoppingCart, which only consists of Item IDs. Therefore, each time you have to look into product.items array that consumes a lot of time. For instance, you have to write this:


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

Changing the state shape breaks mapStateToProps

To avoid time-consuming, insert the shoppingCart in the currentUser and edit the object’s state. For instance, it will look like this:


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

 

If you do this, the mapStateToProps function you wrote earlier will be invalid or broken, which will be more time-consuming. We need a function that helps us to find the desired data. This is why we need selectors.

See Also: ReactJS – prevState in the new useState React hook?

Using Reselect for Better Performance

Before knowing Reselect, we should understand what memoization is. Memoization is a storage facility. Moreover, it stores the previous arguments and results. If the Function returns the same Value for the debate and the inputs between the Function don’t change, you don’t have to carry out the Function again. It also prevents needless re-renders. 

using reselect

If you want to get these memoized selectors, install the Reselect library, which will help boost your performance.  

Driving Data With Redux Selectors: The Reselect Library

A Reselect library consists of several features for creating selectors. Selectors made with Reselect are also memoized. 

In addition, you can use Reselect to build selectors that find and give data within the state tree. Furthermore, we can do this with the help of the createSelector function. There are also various libraries you can practice with, like the Redux-saga typescript, which is a middleware library focusing on improving the maintainability of the code.

Utilizing the createSelector function

To use the createSelector function, use some basic Redux selectors(one or more), like the getProducts selector. The last thing you want is a function to facilitate the results of the basic selector. 

using createselector function

Let’s use the Redux reselect to create a selector that returns the current product. 

  • Firstly, use the createSelector and pass it with the getProducts and getCurrentProductId selectors.
  • Afterwards, pass a function that returns the product deriving out of the Immutable.js of products given by getProducts. To bring out the current product, we need to use the get() method on it and pass the result of the getCurrentProductId selector. For instance:

// Assuming we have these basic selectors
const getProducts = function(state) {
  return state.products;
};

const getCurrentProductId = function(state) {
  return state.uiState.currentProductId;
};

import { createSelector } from "reselect";

export const getCurrentProduct = createSelector(
  getProducts,
  getCurrentProductId,
  (
    // Function to process the results of the basic selectors
    products, // Value returned by the getProducts selector
    currentProductId // Value returned by the getCurrentProductId selector
  ) => {
    return products.get(currentProductId);
  }
);

See Also: JavaScript vs ReactJS: A Comparative Analysis

Fixed Data Structures

Redux needs the objects in the store to be immutable; in other words, they cannot be changed after creation. This also avoids changes to the state without needing Reducers. Objects can be restored with altered copies, though. We can also use react state management without Redux, with the help of the state hook to a particular component.   

data structures in redux

We can also use the Immutable.js library for the data entered in the Redux store to meet this requirement. Moreover, the immutable data structures displace JavaScript’s integrated data types. 

When you displace with JavaScript arrays, it is known as a list, whereas when you replace JavaScript Objects, it is known as a map. These structures cannot be differentiated or changed with standard JavaScript operators. Immutable.js gives functions and techniques for determining objects and making altered copies.

The Reselect Fixed Helpers library

You can use a helper library called reselect-immutable-helpers that helps you work easily with Redux selectors and Immutable.js objects. Before using the selectors, testing is done with the help of Redux toolkit testing. This also ensures the smooth functioning of the selectors.  

redux library

Immutable objects are very handy but unclear when writing for React components. The reselect-immutable-helpers will help you change JavaScript objects to Immutable.js objects when needed. It also has functions for understanding the construction of selectors across a tree of Immutable.js objects.

Utilizing the createPropsSelector function within mapStateToProps

When we write mapStateToProps, it follows a pattern. It functions with selectors to give back an object, with each key having the result of a specified selector. Additionally, the createPropsSelector function utilizes this without having to pass frequently in the state to every selector. For instance, you can write:

mapstatetoprops


const mapStateToProps = createPropsSelector({
  title: getProductTitle,
  price: getProductPrice,
  image: getProductImage
});

 

That is also equivalent to:


const mapStateToProps = state => {
  return {
    title: getProductTitle(state),
    price: getProductPrice(state),
    image: getProductImage(state)
  };
};

createPropsSelect Function takes the help of Reselect, which also makes a memoized selector function. Memoization helps you utilize the fixed checks in react-Redux, too. In the example above, if all the product details are the same from one update to another, the mapStateToProps will return the exact object both times. You can use the connect() Function to see if the result is the same. Moreover, you can prevent needless re-renders without using another method.

See Also: 6 Best Web Development Books: Top Recommendations for 2024

By the createGetSelector function

The createGetSelector function covers the .get method of the Immutable.js object that uses Reselect to lessen the continual code of changing the Immutable.js object to a JavaScript object. The createGetSelector function follows some guidelines which are:

creategetselector function

  1. A selector that gives back an Immutable.js object
  2. A key/selector that gives back a key
  3. A default value(optional)

CreateGetSelector is advantageous when you have an established key you already know when the selector was made. For instance: 

 const getProductTitle = createGetSelector(getProduct, "title", ""); 

That is equivalent to: 

 const getProductTitle = createSelector(getProduct, product =>
  product.get("title", "")
); 

Utilizing the createHasSelector function

This Function is very similar to the previous one. It uses .has() instead of the .get() method. It takes a key/selector like the previous Function. For instance:

const isCurrentCategoryLoaded = createHasSelector(
  getCategories,
  getCurrentPath
);

This is equivalent to:

const isCurrentCategoryLoaded = createSelector(
  getCategories,
  getCurrentPath,
  (categories, currentPath) => categories.has(currentPath)
);
 

Best Approaches

One of the best approaches could be naming the selector function with the word “selector”. Another common approach would be using the selector with a reducer. This will remind you to alter your selector whenever the state is changed. For instance: todo app

// Reducer
function todoApp(state = [], action) {
switch (action.type) {
  case GET_ALL_TODOS:
    return {
      todos: action.data.todos
    };
  default:
    return state;
}
}
// Selector
function getIncompleteTodos(state) {
 return state.todos.filter((todo) => {
   return !todo.completed
 });
}

Instead of using the mapStateToProps function, that is:


function mapStateToProps(state) {
 return {
   incompleteTodos: state.todos.filter((todo) => {
     return !todo.completed
   });
 }
}

We could use a new selector. For instance:

function mapStateToProps(state) {
 return {
   incompleteTodos: getIncompleteTodos(state)
 };
}

The code is clearer, and updating the state tree when necessary will be easy. 

See Also: Working With Data: How To Import JSON Files In React

 FAQs

What is the use of createSelector?

React createSelector uses one or more selectors and gives back another selector that is usable.

What is the use of reselect react?

React reselect consists of the createSelector function that is used to make more selectors.

What are the selectors in Redux?

Selectors are a function that holds the Redux state from the Redux store as an argument and returns some value to the component.

What is the useSelector selector function?

It helps you to get the data from the Redux store state to use it in the component.

Conclusion

In conclusion, we learned how to use various Redux selectors and React selectors in detail. It’s important to understand these selectors, as programmers use them daily, too. Moreover, you can also try various selectors and learn more about them in detail. When discussing React and Redux, we should always know which will give us an advantage.

When we compare the react query with Redux, we will see reducers are the best option for state management. Therefore, you should query Redux vs React query to find the best option.

Leave a Comment