Tips and tricks for accessing the state tree within effects in @ngrx/effects 2.x

I am currently in the process of migrating my code from version 1.x to 2.x of @ngrx/effects.

Previously, in version 1.x, I was able to access the state tree directly within an effect:

  constructor(private updates$: StateUpdates<AppState>) {}

  @Effect() bar$ = this.updates$
    .whenAction(Actions.FOO)
    .map(obj => obj.state.user.isCool)
    .distinctUntilChanged()
    .filter(x => x)
    .map(() => ({ type: Actions.BAR }));

However, with the upgrade to version 2.x, I have noticed that now only the action is provided. Is there still a way for me to obtain access to the state tree within the effect? Or should I consider avoiding this approach as it may not be best practice anymore?

  constructor(private actions$: Actions) {}

  @Effect() bar$ = this.actions$
    .ofType(ActionTypes.FOO)
    .map((obj: any) => {
      console.log(obj);              
      return obj.state.user.isCool   
    })
    .distinctUntilChanged()
    .filter(x => x)
    .map(() => ({ type: ActionTypes.BAR }));

Answer №1

To add to the options, you can also utilize .withLatestFrom(this.store) in your code. The modified code snippet would look like this:

  constructor(
    private actions$: Actions,
    private store: Store<AppState>
  ) {}

 @Effect() bar$ = this.actions$
    .ofType(ActionTypes.FOO)
    .withLatestFrom(this.store, (action, state) => state.user.isCool)
    .distinctUntilChanged()
    .filter(x => x)
    .map(() => ({ type: ActionTypes.BAR }));

Answer №2

Effects don't have to be defined as class properties; they can also be implemented as methods. This allows you to access a store that is injected into the constructor.

As of the time I wrote this response, there was some ambiguity regarding property declarations and usage of public/private constructor parameters. If properties are declared after the constructor, they can still access the public/private members initialized via constructor parameters - which means you do not necessarily need to declare effects as functions.

By utilizing the injected store, you can leverage operators like mergeMap to retrieve the state and merge it with the received update:

@Effect()
bar$(): Observable<Action> {

  return this.actions$
    .ofType(ActionTypes.FOO)
    .mergeMap((update) => this.store.first().map((state) => ({ state, update })))
    .map((both) => {
      // Perform necessary operations using both.update and both.state.
      return both.update;
    })
    .distinctUntilChanged()
    .filter(x => x)
    .map(() => ({ type: ActionTypes.BAR }));
  }
}

The decision of whether or not this approach aligns with best practices is subjective. Extracting state information - possibly through an ngrx-style selector - seems logical, but having all required data for an effect within its associated action would lead to cleaner code.

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

Properly defining a DI service in Angular 2.1.2 using ES5

I have created an Angular 2 service that utilizes the Http service and is accessed by other components. However, I am unsure if my implementation is correct: (function (app) { 'use strict'; app.LoaderService = ng.core.Component({ providers: ...

Adding typing to Firebase Functions handlers V2: A step-by-step guide

Here's a function I am currently working with: export async function onDeleteVideo(event: FirestoreEvent<QueryDocumentSnapshot, { uid: string }>): Promise<any> { if (!event) { return } const { disposables } = event.data.data() ...

Error: Unable to iterate through posts due to a TypeError in next.js

Hi there, this is my first time asking for help here. I'm working on a simple app using Next.js and ran into an issue while following a tutorial: Unhandled Runtime Error TypeError: posts.map is not a function Source pages\posts\index.tsx (1 ...

Exploring the optimal procedures to asynchronously request an external API in Node.js using TypeScript

When handling a POST API request in a Node.js application built using TypeScript, it's necessary to make a call to an external API. This external API operates independently and must run in the background without impacting the response time. How can t ...

addImportToModule function results in a return of an empty changes array

I'm currently experimenting with angular schematics to include imports in NgModule. My application is built using Angular 16.2.5. Below is the code snippet of the logic I am working on: import { addImportToModule, insertImport} from '@schematics/ ...

Unable to modify data with ionic and firebase in child node format

I am encountering an issue when updating data with Ionic Firebase using the following code. Instead of rewriting the previous data, it simply creates new data entries. Here is the code snippet: updateLaporan() { this.id =this.fire.auth.cur ...

Quicker component refreshing in the Angular framework

Two Angular components were created, one for adding a new post and another for displaying all posts. Clicking the create post button redirects to the PostList component, which shows all posts. To automatically load the new post without manual refreshing, w ...

I'm having trouble importing sqlite3 and knex-js into my Electron React application

Whenever I try to import sqlite3 to test my database connection, I encounter an error. Upon inspecting the development tools, I came across the following error message: Uncaught ReferenceError: require is not defined at Object.path (external "path ...

Angular SwitchMap is a powerful operator that allows you

I am currently utilizing the mat-table component from angular material, in conjunction with pagination features. Whenever a user inputs text into the search field, a filter method is activated to send the text, page size, and current page to the backend f ...

The problem with Angular Jasmine Karma is with the [SortKey] and various elements present on the page

While working on building some pages and integrating jasmine .spec files for karma to run with Angular 5, I encountered numerous errors. For example, when using Chrome and checking the command prompt, I came across: Error: Template parse errors: Can& ...

Guide on Implementing jQuery Plugin with Vue, Webpack, and Typescript

I am currently exploring the integration of the jQuery Plugin Chosen into my vue.js/Webpack project with TypeScript. After some research, I discovered that it is recommended to encapsulate the plugin within a custom Vue component. To kick things off, I m ...

Contact creation not working on non-HubSpot form popups

I'm currently experiencing an issue with my website that has non-Hubspot forms. We have successfully integrated the tracking code to generate cookies for users, track their sessions, and enable the non-Hubspot forms. However, we are facing a problem s ...

Angular application hosted on Apache2 with SSL configured to communicate with a Spring Boot API running on port 8080

After developing a small application using Angular and an API with Spring Boot that includes an embedded Tomcat server, I decided to deploy them on a Raspberry Pi while configuring an SSL certificate with Let's Encrypt. The deployment process involve ...

How to invoke a function from a different controller in Ionic 2

Is it possible to call a function in another controller within Ionic 2? Here is my code where I want to call the loadPeople function in the tab controller. home.ts import { Component } from '@angular/core'; import { NavController } from ' ...

The functionality of data binding becomes unclear when the ngif directive is applied to a mat-selection-list in

I am facing an issue with displaying a mat-selection-list based on a condition. Since adding the ngif condition, the data is consistently being set to undefined. I am struggling to identify the root cause of this problem. Thank you in advance for your assi ...

The Angular array stays undefined when JSON data is being passed

I am facing an issue with my API that provides JSON data related to football matches. Even after passing this data to the frontend (angular), I am encountering a problem where the array remains undefined. JSON Data: "match_id":"194200", "country_id":"41" ...

Exploring the concept of data model inheritance in Angular 2

In my Angular2 and ASP.NET Core project, I have set up the following: My C# .NET Core API returns the following classes: public class fighter { public int id { get; set; } public string name { get; set; } public datetime birthdate { get; set; } p ...

ESLint warning: Potentially risky assignment of an undetermined data type and hazardous invocation of an undetermined data type value

Review this test code: import { isHtmlLinkDescriptor } from '@remix-run/react/links' import invariant from 'tiny-invariant' import { links } from '~/root' it('should return a rel=stylesheet', () => { const resp ...

Support for BigInt is not available in TypeScript version 3.5.*

It seems that TypeScript has supported BigInt since version 3.2, and my project is using TypeScript 3.5. Despite not explicitly declaring any variables as BigInt, I recently integrated a package called BufferUtility from https://github.com/Pharuxtan/Buffer ...

Using MUI-X autocomplete with TextField disables the ability to edit cells

When I double-click on a cell, everything works fine. However, after the second click to start editing the textfield, the cell stops editing. I can still choose an option though, so I believe the issue lies somewhere in the textField component, possibly i ...