@ngrx/effects, ngrx ofType

Exploring the inner workings of typeOf effects in Ngrx has been intriguing for me lately. Consider this scenario:

....

@NgModule({
    imports: [
        EffectsModule.forRoot([TodosEffectsService])
],

....

Imagine I have defined the following effect files:

@Effect() createTodos$ = this.actions$
.ofType(CREATE_TASK)
    .map(() => {
        console.log('called');
            return { type: 'OTHER'};
});

@Effect() addTodos$ = this.actions$
.ofType(CREATE_TASK)
    .map(() => {
        console.log('called');
            return { type: 'OTHER'};
});

I am trying to grasp how, at runtime, when I dispatch an action, whether the `action$` is subscribed and executes `ofType` every time to match the type, or if it only does so once?

If it runs only once, then how do the effects know which one to subscribe and execute every time a new action is dispatched?

Your insights are appreciated. Thank you!

Answer №1

Essentially, when the .ofType() method is invoked, it subscribes to the source stream of actions and only passes matching actions to the resulting stream. This means that it is called just once.

If we delve into the source code, we can see that behind the scenes, the ofType function utilizes the filter operator from the rxjs library. In essence, this.action$.ofType(CREATE_TASK) can be equated to:

this.action$.filter(action => action.type === CREATE_TASK)

To understand how the filter operation functions, you can refer to the documentation provided by rxjs here:

Similar to the familiar Array.prototype.filter method, this operator extracts values from the source Observable, applies them through a predicate function, and emits only those values that resulted in true.

It's important to note that each effect accepts an observable (this.action$) as input and yields a fresh observable which is subscribed to only once during initialization. The returned observable dictates how actions from the input observable are altered, without impacting the source observable itself.

In your scenario, the ofType() method generates a new observable that monitors the this.action$ stream and emits solely actions meeting the condition action.type === CREATE_TASK. Following that is the map operator, which also produces a new observable observing the one returned by the ofType() invocation and modifies each received action according to a specified projection function. However, all these observables are established once at initialization and simply allow actions to pass through, filtering and transforming them as needed upon dispatch.

If you wish to enhance your comprehension of rxjs, I recommend delving into André Staltz's talk on "You will learn RxJS". It should provide valuable insights into the world of observables and their functionality.

Answer №2

Each time your action is dispatched, the this.actions$.ofType(CREATE_TASK) function will be called after your reducer case is executed. like Redcucer

switch(action) {
case youractionsname.CREATE_TASK : {
// pure function logic here
   }
}

The first reducer will execute followed by checking any effects with the type 'CREATE_TASK'. In a subscription pattern, all subscribed functions are stored in an array based on conditions. When you dispatch an action that meets the condition, all corresponding functions will be called.

Answer №3

The purpose here is to highlight the lack of export for ofType in the Actions class within ngrx/effects, requiring a specific approach to use it: 1- Start by importing ofType from ngrx/effects as shown below:

import { Injectable } from "@angular/core";

import { Effect, Actions, ofType } from "@ngrx/effects";
import * as omid from "@ngrx/effects";
import { of } from "rxjs";
import { map, switchMap, catchError } from "rxjs/operators";
@Injectable()
export class PizzasEffects {
  constructor(
    private actions$: Actions,
    private pizzaService: frtomServices.PizzasService
  ) {}

  @Effect()
  LoadPizzas$ = this.actions$.pipe(
    ofType(pizzaActions.LOAD_PIZZAS),
    switchMap(() => {
      return this.pizzaService.getPizzas().pipe(
        map(pizzas => new pizzaActions.LoadPizzasSuccess(pizzas)),
        catchError(error => of(new pizzaActions.LoadPizzasFail(error)))
      );
    })
  );
}

Answer №4

In addition to that, you have the capability to send out an array of actions from every effect.

Explore this intriguing article on our website

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

Error: Unable to inject HttpClient dependency. Angular 5

I recently switched to using the Angular template in Visual Studio 2017 and decided to update to Angular 5.2. However, I encountered an error while trying to make a http call from the service class. The error message I received is: https://i.sstatic.net/p ...

What are the steps to fix the error stating that 'loginError.data' is an unknown type?

Recently delving into typescript, I decided to test the waters with nextjs, rtk query, and antd. However, while attempting to access error within useLoginMutation using the property error.data.message, it was flagged as type unknown. To tackle this issue, ...

Having trouble sending a request to a third-party API

Currently, I am developing an application using Ionic 2 that integrates a third-party API from Oxford Dictionary. This API requires an app_id and app_key for authentication purposes. Below is the service that sends a GET request to the API @Injectable() ...

Strategies to prevent fortuitous success in testing

I have the following test case: it('is to display a welcome message', () => { spyOnProperty(authServiceSpy, 'token').and.returnValue(environment.testAuthenticationToken); let teacher: Teacher = authServiceSpy.token.teacher; ...

Verify that the lower limit is not higher than the upper limit set in an Angular application

In my Angular application, I have two input fields for minimum and maximum values. I want to display an error message if the user enters a minimum value greater than the maximum value provided, or the default maximum value if none is provided. The form is ...

Unique component for customized form controls

Currently, I am delving into the world of Angular. One challenge I have been tackling is creating a custom form control that includes a mat-select. The goal is for the submitted form value to be the item selected in the dropdown. After sifting through num ...

Steps to create a clickable row with color change in Angular 4

How do I make an entire row clickable and change the row color when a checkbox is clicked? This is my HTML file: <section class="others"> <div class="sub-header">Others</div> <p class="text-center" *ngIf="otherTests.length === 0"> ...

What is the rationale behind permitting surplus properties in Typescript interfaces even though all properties are declared as optional?

Exploring the code snippet... interface Options { allowed?: string; } function test(options: Options) { return options; } const options = { allowed: 'allowed', notAllowed: 'notAllowed', }; test(options); // no error thrown ...

Is the async pipe the best choice for handling Observables in a polling scenario

The situation at hand: I currently have a service that continuously polls a specific URL every 2 seconds: export class FooDataService { ... public provideFooData() { const interval = Observable.interval(2000).startWith(0); return interval ...

Creating Production Files for Web using RxJs and TypeScript

I am interested in developing a JavaScript Library using RxJs (5.0.0-Beta.6) and TypeScript (1.8.10). My TypeScript file is successfully compiling. Below are the files I have: MyLib.ts: /// <reference path="../../typings/globals/es6-shim/index.d.ts" ...

Access a child route using a named router outlet

My ngtabcontent requires dynamic content generation, so I have created child routes for the PersonalComponent. Upon clicking next, the navigation should move to its child route. const routes: { path: '', redirectTo: 'tenant', pathM ...

Using Ng If with a boolean value to dynamically update the title of a webpage

On my Stock page, I have multiple fields labeled as Title 1. https://i.sstatic.net/FpCsW.png When I run a console.log, it indicates that I am on the first page! ngOnInit() { this.currentPortfolio = this.shrd.getData('currentPortfolio'); ...

Setting up Weblogic application server for an Angular application: A Step-by-Step Guide

I am facing a deployment issue with my Angular (6.1) application that is packaged in a WAR and EAR file for deployment on a Weblogic server (12c). According to the guidelines provided here, all requests should be directed to the application's index.ht ...

Encountering a TS(2322) Error while Implementing Observables in Angular 12

Exploring the intricacies of Angular 12 framework, I find myself encountering a hurdle in my learning journey. The tutorial I am following utilizes the Observable class to query fixed data asynchronously. However, an unexpected ts(2322) error has surfaced ...

The addition of special characters to strings in TypeScript through JavaScript is not functioning as expected

I need assistance on conditionally appending a string based on values from captured DOM elements. When the value is empty, I want to include the special character "¬". However, when I try adding it, I get instead because the special character is not reco ...

Troubleshooting with matTootip on Safari: Tips for avoiding input-text blockage

I am currently using the matTooltip feature from Angular Material for an input field. However, on Safari, the input field appears to be overlapping, making it impossible to type in. Despite my attempts to change the position of the toolTip, the issue pers ...

Styling with Css Attributes and Text Formatting Styles

I am working with a custom textStyle that is of type TextStyle, coming from react-native types, or React.CSSProperties. I want to apply this styling to an html span element using the style attribute. The style attribute only accepts types of React.CSSPrope ...

Utilizing the Angular *ngFor directive to iterate through JSON data

Just stepping into the world of Angular, I want to share a brief overview of my goal since the code is lengthy. Here's the relevant part: Within my project, I have a list display component. And I have two components, namely animals and zone. For in ...

Using Typescript generics within a callback function

I am currently working on developing a versatile service that can fetch data from a remote source and create objects based on that data. @Injectable() export class tService<T> { private _data: BehaviorSubject<T[]> = new BehaviorSubject([]) ...

DatePipe incorrectly displays date format

I am currently working with Angular version 12 and using datePipe.transform. I have a date in the format dd/MM/yyyy as a string, and I want to bind this date into my reactive form for editing. The reactive form includes an Angular Material date picker comp ...