Selectors in Redux are functions used to extract and derive data from the Redux state tree. In Redux applications, the global state is stored as a single object. Since this state tree can be very large and contain numerous distinct data fragments, directly accessing the data can be both cumbersome and time-consuming. Selectors exist to simplify accessing data from the state tree.
Selectors' primary responsibilities and roles include:
-
Abstract state structure: Selectors provide an abstraction layer that allows components to read state without needing to know the specific structure of the state tree. This means that if the state tree structure changes, only the relevant selectors need updating, without requiring modifications to all components that use this part of the state.
-
Compute derived data: Selectors can be used to compute derived data, which involves generating new data representations based on raw data in the state tree. For example, filtering objects from an array of multiple objects that meet specific conditions, or calculating the sum of certain data.
-
Optimize performance: With libraries like Reselect, selectors can avoid unnecessary computations through memoization techniques. This means the selector only re-computes when its inputs (i.e., the relevant parts of the state tree) change; otherwise, it returns the result from the previous computation, thereby improving application performance.
-
Ensure reusability and composition: Selectors can be reused across different components and combined to build more complex selectors, which helps reduce code redundancy and maintain logical consistency.
Example
Suppose we have a Redux state that includes a product list, where each product has a price and a category. If we want to retrieve the total price of all electronic category products, we can write a selector to achieve this:
javascript// state structure example const state = { products: [ { id: 1, name: 'mobile phone', category: 'electronics', price: 599 }, { id: 2, name: 'tablet', category: 'electronics', price: 799 }, { id: 3, name: 'watch', category: 'accessories', price: 199 } // more products... ] }; // Selector const selectElectronicProductsTotalPrice = (state) => { return state.products .filter(product => product.category === 'electronics') .reduce((total, product) => total + product.price, 0); }; // Use Selector const totalPrice = selectElectronicProductsTotalPrice(state); console.log(totalPrice); // Output should be 1398
In this example, selectElectronicProductsTotalPrice is a selector that first filters out all products in the electronic category and then calculates and returns the sum of their prices. This approach not only encapsulates the query logic for the state tree but also makes this logic easier to test and reuse.