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

This error occurs because the argument type 'AsyncThunkAction<any, void, {}>' cannot be assigned to a parameter of type 'AnyAction'

I encountered an error that I couldn't find a solution for on Stack Overflow The argument of type 'AsyncThunkAction<any, void, {}>' is not compatible with the parameter of type 'AnyAction'. <MenuItem onClick={() =&g ...

Cloud Function scheduler incorporating dynamic memory allocation control

I am currently working on setting up a scheduled function in Firebase Cloud Functions that interacts with third-party APIs. However, I am facing an issue with the memory limit being exceeded due to the large size of the data processed by this function. Al ...

Retrieving the output from a nested function within a function in a Node.js application connected to a

I'm currently working on a basic web application that interacts with a database by performing INSERT and SELECT operations on a single table. While I have utilized a function from various tutorials, I am struggling to retrieve the results from the SEL ...

Leveraging the result of one ajax function within a different ajax function

My current project involves the following steps: 1. User creates a template with various elements. 2. When the user clicks a button: *The first ajax function establishes a new entry in the custom template database. *The second ajax function retrieves the ...

Tips for adding animation to a React state value change triggered by an input

In my React application, I have a form with multiple fields that each contain a text input and a range input. Currently, both inputs share the same state value and onChange function to keep them synchronized. However, I would like to add an animation effe ...

When using the npm command, errors may occur that are directly related to the lifecycle and initialization

Currently, I am delving into the world of OpenLayers and JavaScript. I came across a helpful tutorial that provides step-by-step guidance on creating a simple OpenLayers project using JavaScript. I followed the instructions diligently but encountered an er ...

Using asynchronous functions in a loop in Node.js

Although this question may have been asked before, I am struggling to understand how things work and that is why I am starting a new thread. con.query(sql,[req.params.quizId],(err,rows,fields)=>{ //rows contains questions if(err) throw err; ...

Creating keys from extensive JSON data without having to manually match types using Typescript

Is there a way to efficiently parse and access the values in large JSON files using Typescript, without the need to manually define interfaces for all expected key/value pairs? In the past, working with small JSON files required only extracting a few spec ...

Address aliases in the webpack configuration file

When utilizing webpack, it is possible to write the configuration file using TypeScript. However, it is crucial to ensure that any alias paths present in the config file are resolved to their mapped paths. It should be noted that this pertains specificall ...

Error: The function expressJwt is not recognized as a valid middleware

As I delve into learning about middlewares, I encountered an issue when trying to import express-jwt. The syntax I used was: const expressJwt = require('express-jwt') To address the problem, I uninstalled the current version of express-jwt and i ...

The Challenge of Scope in JavaScript

I'm currently facing an issue with executing ajax requests using jQuery. The sequential order in which I am attempting this is as follows: Click the button Make an ajax post request Invoke a function that resides outside the current scope upon compl ...

Retrieving a value attribute from the isolated controller of a directive

I have a directive that reads and writes attributes, but I'm having trouble getting it to work as expected. The issue seems to be with the controller inside main-directive.js, which is empty, while the actual action is happening in the isolated direct ...

The properties are absent in Angular Service - Observable

I recently started learning angular and I'm struggling to make this HTTP get request work. I have been looking at various examples of get requests for arrays and attempted to modify one for a single object (a user profile) but without success. The err ...

Generating various API calls and delivering them to a template (Express + Node.js + Facebook open graph)

I am currently developing a unique Express Node.js application that utilizes the extraordinary capabilities of this remarkable Facebook SDK. Allow me to present my existing route for the root: app.get('/', Facebook.loginRequired(), function (req ...

The JSON file gets emptied every time I refresh the page repeatedly

I am encountering an issue where my JSON file gets cleared if I restart the page quickly after using the fs module to read/write it. The JSON data is read at the beginning of the page like this: let preferencesJSON; try { preferencesJSON = fs.readFile ...

Getting AJAX parameters from Angular in Node/Express Js

I am encountering an issue with my factory, which sends an ajax userId call to my node server. usersModel.getUser = function(userId){ return $http({ method: 'GET', url: 'http://localhost:3000/users/details', ...

I encountered an error from DataTables when trying to set the width of the header cells using the original width of the columns

                 Help! I keep getting an error message: DataTable Uncaught TypeError: Cannot read property 'style' of undefined Does anyone have any ideas on how to fix this?   I keep seeing the following error message: Uncaught Typ ...

Ways to transfer an Object from a service to a component

I'm currently working on my website and trying to implement a cart feature where users can add items. To achieve this, I have created a service that contains the cart as an object called cart. The service has functions to add items to the cart and ret ...

Struggling to delete event listeners in TypeScript using object-oriented programming with JavaScript

After researching the issue, I have discovered that the onMouseUp event is being fired but it is not removing the EventListeners. Many individuals facing a similar problem fail to remove the same function they added initially. Upon reading information fr ...

What is the ideal destination for my Ajax request to be sent?

When utilizing jQuery, in the event of sending an Ajax request you must provide the URL to direct towards. For instance: $.get("someurl", function(data) { console.log(data); }); The query at hand is: should the URL indicate a page on the server, trea ...