Efficient cached selector with computation in @ngrx/store

Here is the structure of my normalized ngrx store:

export interface State {
    carts: EntityState<Cart>;
    items: EntityState<Item>;
}

export interface Cart {
    id: number;
    maxVolume: number;
}

export interface Item {
    id: number;
    cartId: number;
    volume: number;
}

In this setup, a cart can hold multiple items. My goal is to have a selector that returns an array of all carts with arrays containing their items and also evaluates if any items are at risk of falling out of their respective carts:

export const select: MemoizedSelector<object, any> = createSelector(
  selectAllCarts, selectAllItems, 
  (allCarts: Cart[], allItems: Item[]) => {
    return allCarts.map(c => {
      const items = allItems.filter(i => i.cartId == i.id);
      return {
        id: c.id,
        items: items.map(i => {
          // Perform computations only when necessary
          // Make sure these computations are memoized
          const computed = isCartOverfilled(i, c, items);
          return {
            id: i.id,
            mightFallOut: computed
          }
        })
      }
    });
});

Whenever an item is updated, the isCartOverfilled function needs to be executed for each related item in the store. However, this function can be computationally expensive and should only run for the items within a specific cart. How can I achieve this?

I attempted to select items from a single cart using the following approach:

export const selectCart = (cartId: number) => createSelector(
  selectItemsByCartId(cartId), selectCartById(cartId),
  (items: Item[], cart: Cart) => {
  return {
    id: cart.id,
    items: items.map(i => {
      const computed = isCartOverfilled(i, cart, items);
      return {
        id: i.id,
        mightFallOut: computed
      }
    })
  }
});

Although this selector avoids excessive computation, it only focuses on one cart. I still need to include all carts in the output. I am uncertain if achieving this with a selector is feasible.

Answer №1

Since the state has already been changed, the selector will recalculate.

Instead of relying on selectors, you can maintain a separate state for the cart. When you dispatch the addCartItem action, you can directly update the cart with a single item.

export interface State {
    carts: EntityState<Cart>;
    cartOverFilled: SomeState or part of Cart State <---
    items: EntityState<Item>;
}

or

export interface State {
    carts: EntityState<CartState>;
    items: EntityState<Item>;
}

export interface CartState {
    cart: Cart;
    overFilled: any
}

export interface Cart {
    id: number;
    maxVolume: number;
}
  1. Add an additional state with values to check if it is overfilled;
  2. Create an effect for type 'Add to cart '
  3. Create another action to recalculate the existing state of overfilled with the incoming item.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unable to locate a type definition file for module 'vue-xxx'

I keep encountering an error whenever I attempt to add a 3rd party Vue.js library to my project: Could not find a declaration file for module 'vue-xxx' Libraries like 'vue-treeselect', 'vue-select', and 'vue-multiselect ...

React TypeScript - Module not found

Organizational structure: src - components - About.tsx In an attempt to optimize performance, I am experimenting with lazy loading: const About = React.lazy(() => import('components/About')); However, Visual Studio Code is flagging &ap ...

Encountering a hiccup while trying to install Svelte, Skeleton, and Tail

Recently entering the world of Svelte and TypeScript, I have encountered some unexpected errors after installation. Despite following the same steps as before, I am puzzled by what is causing these issues. This is the process I followed: npm create svelte ...

Angular fails to show route after successful login

Within my application, I have divided it into two areas: the admin area (referred to as iwti) and the 'retaguarda' area. The 'retaguarda' section is functioning correctly, but when I navigate to the route /iwti, the layout within the &l ...

Is there a way to detect and handle errors triggered by a callback function?

My component has the following code snippet: this.loginService.login(this.user, () => { this.router.navigateByUrl('/'); }); Additionally, my service contains this method: login(credentials, callback) { co ...

What is the process for transforming a Typescript source file into JavaScript?

I have a basic HTML file with a script source set to index.ts. index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge ...

The width of mat-table columns remains static even with the presence of an Input field

I'm currently working on an Angular component that serves the dual purpose of displaying data and receiving data. To achieve this, I created a mat-table with input form fields and used {{element.value}} for regular data display. Each column in the tab ...

Issue: The variable 'HelloWorld' has been declared but not utilized

Why am I encountering an error when using TypeScript, Composition API, and Pug templating together in Vue 3? How do I resolve this issue when importing a component with the Composition API and using it in a Pug template? ...

Issue: The parameter "data" is not recognized as a valid Document. The input does not match the requirements of a typical JavaScript object

I encountered the following issue: Error: Argument "data" is not a valid Document. Input is not a plain JavaScript object. while attempting to update a document using firebase admin SDK. Below is the TypeScript snippet: var myDoc = new MyDoc(); myDo ...

Initial position of the range slider in IONIC 2

I have been searching the web extensively to find a solution to this particular issue. I am working with a range slider and trying to set its default starting values, but so far, I haven't had any luck. I've checked both the official documentatio ...

Angular and Node version discrepancies causing problems

This particular CLI version is designed to work with Angular versions ^11.0.0-next || >=11.0.0 <12.0.0, however an Angular version of 13.0.0 was detected instead. If you need assistance with updating your Angular framework, please refer to the follo ...

The issue at hand is that the property 'Draw' is not found within the 'Control' type

I am working on integrating a map component using leaflet and other leaflet plugins. However, I am facing an issue where the other plugins do not seem to work with TypeScript for some unknown reason. For instance, I am encountering a problem when trying t ...

Struggling with "Content" not being recognized in Typescript PouchDB transpilation errors?

I have been diligently working on an Ionic app for the past three months with no major issues during development or deployment to mobile devices. However, yesterday I encountered a frustrating NPM dependency problem while trying to deploy to mobile. In an ...

What types should be used when passing a NgRx Action as a parameter to a function?

Within my Effects function, I have implemented the following code structure. I have included a few lines of code for the catchError block to ensure that: Any errors are handled by the state/store The errors are forwarded to the global error handler / Int ...

Utilizing TypeScript: Importing a typed module within a d.ts file (from an npm package)

I am currently working on integrating a definition file into an npm package that has dependencies on React. The specific library in question can be found at https://github.com/eiriklv/react-masonry-component. In my TypeScript project, I have successfully ...

Guide to showcasing JSON Array in an HTML table with the help of *NgFor

Struggling to showcase the data stored in an array from an external JSON file on an HTML table. Able to view the data through console logs, but unable to display it visually. Still navigating my way through Angular 7 and might be overlooking something cruc ...

Typescript compiles only the files that are currently open in Visual Studio

In my Visual Studio Typescript project, I am in the process of transforming a large library of legacy JavaScript files by renaming them to *.ts and adding type information to enhance application safety. With over 200 files to modify, it's quite a task ...

Is there a way to access the value of a public variable within the @input decorator of a function type?

I am working on a dropdown component that utilizes the @Input decorator to define a function with arguments, returning a boolean value. dropdown-abstract.component.ts @Input() public itemDisabled: (itemArgs: { dataItem: any; index: number }) => boo ...

Communication between Angular services and the issue of 'circular dependency detected' alerts

I am encountering a circular dependency issue with my AuthenticationService and UserService. The UserService is included within the AuthenticationService, but when I try to use AuthenticationService in UserService as shown below: constructor(private authS ...

encountered an issue while accessing a FastAPI-based API

While developing a login feature in Next.js, I encountered an issue when making a request to an API created in FastAPI to retrieve a cookie. The problem arises during the fetch operation on the frontend specifically when setting credentials to 'includ ...