SoFunction
Updated on 2025-03-10

Explain details what is MemoizedSelector in @ngrx/store development package

1. Understand Memoized Selector

exist@ngrx/storeIn the development package,MemoizedSelectoris an important concept and tool for managing and selecting fragments of Redux state in Angular applications. It is@ngrx/storeA key feature of  by usingreselectLibrary to optimize state selectors.MemoizedSelectorThe performance of the state selector can be improved and unnecessary state calculations can be avoided, thereby improving the efficiency and responsiveness of the application.

In this article, we will gain a deeper understanding ofMemoizedSelectorThe concept and usage of  , and use specific examples to illustrate its usage and advantages.

State management is very important in Redux applications. use@ngrx/storeThe development package can easily implement the Redux mode in Angular applications. Where, the selector is a function used to obtain a specific data fragment from the Redux state tree. The selector allows us to organize and reuse state read logic in our application.

@ngrx/storeThe selectors in   are divided into two categories:

  • Normal selector: A new result is calculated and returned every time it is called. This can cause performance issues, especially when computed in complex states.
  • Memoized selector (MemoizedSelector): UsereselectA selector implemented by the library. The Memoized selector caches the calculated results and returns the cached results directly under the same input conditions without recalculating. This avoids unnecessary computing and performance losses.

2. Usage of Memoized Selector

In Angular applications, we usually usecreateFeatureSelectorandcreateSelectorFunctions to define Memoized selectors.createFeatureSelectorUsed to create selectors under a specific feature, andcreateSelectorUsed to create specific Memoized selectors.

2.1 Create Feature Selector (createFeatureSelector)

createFeatureSelectorThe function is used to create a selector under a specific feature, which takes the identifier of a specific feature as a parameter and returns a selector function. This selector function selects a state fragment under a specific feature from the root state.

import { createFeatureSelector } from '@ngrx/store';
// Create Feature selectorconst featureSelector = createFeatureSelector<FeatureState>('featureName');

In the above code, we created a name calledfeatureSelectorFeature selector and identifies it with the identifier of the specific feature'featureName'Related. so,featureSelectorWill be used to select from the name'featureName'The status clip under the feature.

2.2 Create a Memoized selector (createSelector)

createSelectorFunctions are used to create a Memoized selector, which receives a series of input selectors (can be Feature selectors or other Memoized selectors), and an output function. The output function is used to select a specific state fragment from the result of the input selector and perform arbitrary conversion or calculation.

import { createSelector } from '@ngrx/store';
// Create Memoized selectorconst memoizedSelector = createSelector(
  featureSelector,
  (featureState) => 
);

In the above code, we created a name calledmemoizedSelectorMemoized selector. It receives fromfeatureSelectorThe resultfeatureStateAs input, then select fromThis status clip. HeresomeDataIt can be a certain attribute under a specific feature or a state obtained through complex calculations.

The Memoized selector will be cachedThe calculation result of   and directly return the cached result under the same input conditions to avoid unnecessary calculations.

2.3 Using the Memoized Selector

The process of using the Memoized selector in an application is very simple. We can call the Memoized selector just like we call a normal function and pass in the required input conditions. The Memoized selector will make status selections based on the input conditions and return cached results or return results after calculation.

// Use Memoized selector(memoizedSelector).subscribe((data) => {
  ('Selected data:', data);
});

In the above code, we pass()Method callmemoizedSelectorMemoized selector and passsubscribeChanges in subscription status. When the state changes,memoizedSelectorThe status selection will be made according to the input conditions and the cached result or calculated result will be returned. Finally, we will see the output of the selected data in the console.

3. Advantages of Memoized Selector

The Memoized selector has many advantages in Angular applications, especially when dealing with complex state calculations:

3.1 Improve performance

The Memoized selector caches the results of the calculation to avoid unnecessary state calculations, thereby improving application performance. When the input conditions of the selector have not changed, the Memoized selector will return the previously cached result directly without recalculating. This is particularly important in large applications and complex state computing, which can reduce the overhead of repeated calculations and improve the response performance of the application.

3.2 Avoid unnecessary status updates

Since the Memoized selector caches the calculated results, when the state changes, the Memoized selector returns a new result only when the data dependent on the input conditions changes. This can avoid unnecessary state updates, reduce unnecessary component re-rendering, and improve application efficiency.

3.3 Support complex state calculation

The Memoized selector is ideal for handling complex state computing logic. By combining multiple selectors and output functions, we can easily implement complex state transitions and calculations. Memoized selector

The caching mechanism ensures that state calculations are performed only when necessary, avoiding duplicate work.

3.4 Code reuse and organization

The Memoized selector allows us to separate state selection logic from components to implement code reuse and organization. We can place complex state selection logic in Memoized selectors and reuse them in different components. This keeps the components simple and easier to maintain.

4. Example: Use the Memoized selector to manage cart status

Now, we demonstrate how to use the Memoized selector to manage complex state logic with a shopping cart example. Suppose we have a shopping cart app that contains multiple items and cart status. Each item has a unique ID, name, price, and quantity. Cart Status is a collection of all items in the cart.

We first define the status interface of the shopping cart:

interface CartItem {
  id: number;
  name: string;
  price: number;
  quantity: number;
}
interface CartState {
  items: CartItem[];
  total: number;
}

Next, we create the shopping cart@ngrx/storeFeature module and define a Memoized selector to manage shopping cart status.

// 
import { createAction, props } from '@ngrx/store';
import { CartItem } from './';
// Add items to cartexport const addToCart = createAction(
  '[Cart] Add To Cart',
  props<{ item: CartItem }>()
);
// Remove items from cartexport const removeFromCart = createAction(
  '[Cart] Remove From Cart',
  props<{ itemId: number }>()
);
// 
import { createReducer, on } from '@ngrx/store';
import { CartState, CartItem } from './';
import { addToCart, removeFromCart } from './';
// Initialize the shopping cart statusconst initialState: CartState = {
  items: [],
  total: 0,
};
// Create a shopping cart status reducerexport const cartReducer = createReducer(
  initialState,
  on(addToCart, (state, { item }) => {
    // Determine whether the product already exists in the shopping cart    const existingItem = ((i) =>  === );
    if (existingItem) {
      // The product already exists, updated quantity and total price      const updatedItems = ((i) =>
         ===  ? { ...i, quantity:  + 1 } : i
      );
      return {
        ...state,
        items: updatedItems,
        total:  + ,
      };
    } else {
      // The product does not exist, add new product to the cart      const newItem: CartItem = { ...item, quantity: 1 };
      return {
        ...state,
        items: [..., newItem],
        total:  + ,
      };
    }
  }),
  on(removeFromCart, (state, { itemId }) => {
    // Delete items from cart by item ID    const updatedItems = ((i) =>  !== itemId);
    const removedItem = ((i) =>  === itemId);
    return {
      ...state,
      items: updatedItems,
      total:  - (removedItem ?  *  : 0),
    };
  })
);

In the above code, we first define the shopping cart status interface.CartStateInterface with productsCartItem. Next, we created two@ngrx/storeThe action:addToCartandremoveFromCart. These actions will be used to modify the status of the shopping cart.

Then we define the status of the shopping cart reducercartReducer, whereonFunctions to handle different actions. existaddToCartIn the processing logic, we judge whether the product already exists in the shopping cart, if it exists, the quantity and total price will be updated, otherwise new products will be added to the shopping cart. existremoveFromCartIn the processing logic, we delete the item from the shopping cart based on the product ID and update the total price accordingly.

Now, let's create a Memoized selector to select a specific data segment from the cart state.

// 
import { createFeatureSelector, createSelector } from '@ngrx/store';
import { CartState } from './';
// Create a shopping cart Feature selectorexport const selectCartState = createFeatureSelector<CartState>('cart');
// Create Memoized selector: select all items in the shopping cartexport const selectCartItems = createSelector(
  selectCartState,
  (cartState) => 
);
// Create Memoized selector: select the total price of items in the shopping cartexport const selectCartTotal = createSelector(
  selectCartState,
  (cartState) => 
);

In the above code, we first usecreateFeatureSelectorFeature selector for creating shopping cartselectCartState. Next, we usecreateSelectorTo create two Memoized selectors:selectCartItemsandselectCartTotalselectCartItemsMemoized selector selects the cart statusitems,andselectCartTotalSelect the shopping cart statustotal

Now we can use these Memoized selectors in our components to select specific data snippets of the cart state.

// 
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { CartItem } from './';
import { addToCart, removeFromCart } from './';
import { selectCartItems, selectCartTotal } from './';
import { Observable } from 'rxjs';
@Component({
  selector: 'app-cart',
  template: `
    <h2>Shopping Cart</h2>
    <div *ngFor="let item of cartItems$ | async">
      <p>{{  }} - Quantity: {{  }} - Price: ${{  }}</p>
      <button (click)="removeItemFromCart()">Remove</button>
    </div>
    <p>Total Price: ${{ cartTotal$ | async }}</p>
  `,
})
export class CartComponent {
  cartItems$: Observable<CartItem[]>;
  cartTotal$: Observable<number>;
  constructor(private store: Store) {
    $ = (selectCartItems);
    $ = (selectCartTotal);
  }
  addItemToCart(item: CartItem) {
    (addToCart({ item }));
  }
  removeItemFromCart(itemId: number) {
    (removeFromCart({ itemId }));
  }
}

In the shopping cart component, we use()Method callselectCartItemsandselectCartTotalMemoized selector to get all items and total prices in the cart. Then, we useasyncPipelines to process Observable data, displaying the shopping cart's product list and total price in real time.

By using the Memoized selector, we can efficiently manage shopping cart status and update the application interface dynamically based on items in the cart.

5. Summary

MemoizedSelectoryes@ngrx/storeAn important concept in the development package, it is used byreselectLibrary to optimize state selectors. Memoized selectors can improve application performance, avoid unnecessary state calculations, and support the processing of complex state logic.

passcreateFeatureSelectorandcreateSelectorFunctions, we can easily create selectors and Memoized selectors under specific features. Memoized selectors are very useful in Angular applications, especially when managing large state trees and complex state computing, which can effectively improve application performance and responsiveness.

In actual development, we should make full use ofMemoizedSelector, and abstract the state selection logic into a reusable selector as much as possible to improve the maintainability and reusability of the code. At the same time, we should also be careful to avoid abuse of Memoized selectors and avoid creating too many selectors that lead to unnecessary memory usage. Taking into account performance and maintainability into account, the rational use of Memoized selectors will help build efficient and scalable Angular applications.

The above is the detailed content of what is the MemoizedSelector in the @ngrx/store development package. For more information about the MemoizedSelector in the @ngrx/store development package, please follow my other related articles!