Subscription date is activated when a different part of the state changes in ngrx

Within my state, I have properties named start and end which store dates. Whenever any other part of the state is modified, the subscription for these start and end dates is triggered.

Here is the subscription implementation:

this.subs.sink = this.store
      .select(fromTransactionReducer.selectStartAndEndDate)
      .subscribe((date) => {
        console.log("range", date);
        this.range.setValue({
          start: date.start,
          end: date.end,
        });
      });

This is the selector function used:

export const selectStartAndEndDate = createSelector(
  selectTransactionState,
  (state) => ({ start: state.start, end: state.end })
);

The dateRange reducer looks like this:

on(transactionActions.UpdateDateRange, (state, { start, end }) => ({
    ...state,
    start,
    end,
  })),

Here is the action to update the date range:

export const UpdateDateRange = createAction(
  "[Transaction Page] Update Date Range",
  props<{ start: Date; end: Date }>()
);

This is the structure of my state:

export interface State {
  transaction: Transaction[];
  cursors: Cursor;
  totalTransactions: number;
  loading: boolean;
  errorMessage: string;
  formErrorMessage: string;
  items_per_page: number;
  pageSizeOptions: number[];
  pageIndex: number;
  searchKey: string;
  formMessage: string;
  start: Date;
  end: Date;
  trans_type: string;
  base_type: string;
}
export const initialState: State = {
  // Initial state values here...
};

Whenever a different action is dispatched, such as

this.store.dispatch(transactionActions.ResetPageIndex());
, the subscription for the date fields is triggered.

Why does this happen?

In my reducer, the start and end dates are only updated when the UpdateDateRange action is dispatched.

Answer №1

In the ngrx framework, the implementation of the select operator relies on the rxjs distinctUntilChanged operator to ensure that a selector only triggers an emission if its result has changed. You can check out the source code for this behavior here: https://github.com/ngrx/platform/blob/a6fe92df3134b7a589a2e95abe0aea183b411f03/modules/store/src/store.ts#L249

By default, the distinctUntilChanged operator uses an equality comparer (you can find more information at https://www.learnrxjs.io/learn-rxjs/operators/filtering/distinctuntilchanged) and remember that 'object references must match!'

Now let's focus on your selectStartAndEndDate selector - it outputs an object.

Moreover, every time it runs, it generates a new instance of the object. Due to this behavior, the comparison in the distinctUntilChanged always results in a mismatch, causing the selector to emit every time.

To address this issue:

// The returned date will be treated as unchanged next time, preventing the selector from firing again
export const selectStartDate = createSelector(
  selectTransactionState,
  (state) => state.start
);

// Similarly here
export const selectEndDate = createSelector(
  selectTransactionState,
  (state) => state.end
);

// Since the input selectors remain constant, this won't trigger a new emission either
export const selectStartAndEndDate = createSelector(
  selectStartDate,
  selectEndDate ,
  (start, end) => ({ start, end })
);

Stackblitz Demo: https://codesandbox.io/s/so-ngrx-selector-emit-1zxg1?file=/src/app/store/selectors.ts

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

What method is the most effective for retrieving the prior slug name in NextJS?

Looking for Help with Retrieving postID? Greetings! I am currently working on a basic post detail page using NextJS. My URL structure is: [postID]/[title].tsx On the post detail page, I need to fetch the post's data based on the postID, which is hig ...

Require assistance in accessing the second tab on a webpage using JavaScript tabs

Currently, I have a web page with two tabs that are initially hidden until the corresponding tab button is clicked. The click event is managed by jQuery. For example, let's assume that tab 1 is the default one when the page loads. Now, I am looking fo ...

What is the process for submitting a form on consecutive URLs?

I have a form that requires input for settings and includes two buttons: one to save the form and another to both save and execute the settings. <form method="post" action="/settings/{{id}}/save"> <!-- input fields --> ...

Vibrant array of colors in AmCharts' line graphs

I'm looking to enhance my graph by having lines between the bullets in different colors based on their direction. For instance, if a line is rising (going from a bullet of smaller value to greater value), it should be green; if a line is falling, it s ...

the proper injection of angular-resource is not being achieved in AMD

I am struggling to get angular.resource.js to work with angular.js. It seems like Angular is loaded but angular.resource is not being recognized. index.html <!doctype html> <html> <head> <script> var require ...

Creating a personalized grid display

I've been trying to achieve the following output with my code, but so far nothing has worked. Can someone help me identify what I may be doing wrong? I'm new to this, so any guidance would be greatly appreciated. (Please ignore the 'undefine ...

An issue arises following an upgrade in Angular from version 9 to version 10, where the property 'propertyName' is being utilized before it has been initialized

I've spent time looking on Google, Github, and Stackoverflow for a solution to this error, but I'm still struggling to fix it. Can anyone offer a suggestion or help? Recently, I upgraded my Angular project from version 9 to version 10, and after ...

Troubles with displaying Google Maps on Ionic Modal

Having trouble displaying the google map in an ionic modal - it shows up fine on the page but not in the modal. Any help would be greatly appreciated, as this is quite frustrating. Below is my controller js and code for the ionic modal. $ionicModal.from ...

Having trouble with Bootstrap's "hidden-xs" class not working and struggling to create a sticky footer for small viewports

Trying to tackle the challenge of making my footer stick to the bottom of the page on smaller screens has been quite troublesome. As a temporary fix, I decided to experiment with hiding the div entirely until I figure out a proper solution. The HTML < ...

Looping through the ajax data to populate ion-item elements

I am currently working on a loop that retrieves user IDs, names, etc. from a JSON file. I am trying to display this data in a list view within an Ionic framework. When I simply use direct alerts in JavaScript, the users are displayed correctly, but when I ...

form controls disappear upon adding form tags

Currently experiencing an issue with angular and forms that I could use some help with. I have a dynamic form that is functioning properly, but now I need to add validations to it. After following this guide, I established the structure correctly. Howeve ...

Creating Test Cases for Service Response Validation

I am currently attempting to unit test an API within my ngOnInit method. The method is responsible for making a call to the service in order to fetch details. If the details are not undefined, an array called 'shoeDataResponse' of type *shoeData ...

How can multiple functions be grouped and exported in a separate file in Node.js?

Is there a way to consolidate and export multiple functions in nodejs? I want to gather all my utility functions in utils.js: async function example1 () { return 'example 1' } async function example2 () { return 'example 2' } ...

Ways to implement distinct service instances for several child components in Angular 2

I have been working on an application that features multiple instances of a similar master-details view along with a search box. To streamline the process, I decided to create a separate module for this common functionality and establish communication betw ...

Avoid circular dependencies in Angular 6 to ensure proper association between modules

When working with TypeScript, how should I handle the scenario where Cat has an owner: Person Person owns a pet: Cat Cat import {Person} from './person' export class Cat { owner: Person constructor(){ this.owner = new Pers ...

Creating and setting a selected option dynamically in Angular 2 for editing purposes

As I attempt to modify a user, I encounter a scenario where the user possesses a non-primitive array of machines. During editing, my goal is to generate new elements with select options and assign the selected value based on the user object: export class ...

Using React MUI Select in combination with react-hook-form does not seem to be compatible with Cypress testing

Within my React application, I have implemented a form that includes a dropdown select. Depending on the option selected from the dropdown, different input fields are rendered. const [templateType, setTemplateType] = useState(""); const { regi ...

Best practice for importing ts files from an npm package

When faced with the need to divide a ts project into multiple repositories/packages for creating microservices, the challenge arises in combining these packages efficiently. Some packages are required in one microservice, others in another, and some in all ...

Utilizing Angular 4 Typescript to create cascading drop-downs within a table

As a newcomer to Angular, I am in the process of building my first application using Angular 4 and TypeScript. I would like to implement Cascading dropdowns within a table using Angular 4. Currently, I am facing an issue where changing the dropdown selec ...

obtain an inner element within a container using the class name in a div

I am attempting to locate a span element with the class of main-tag within a nested div. However, I want to avoid using querySelector due to multiple elements in the HTML file sharing the same class and my preference against using IDs. I realize there mig ...