Executing numerous API requests through ngrx effect

I am still learning about the ngrx store and redux pattern. I've encountered an issue with dispatching the updatePresentation$ effect. This effect is triggered when the updatePresentation action is invoked. Here's how the updatePresentation action is defined:

    export const updatePresentation = createAction(
      '[Presentation] Update presentation',
      props<{ presentation: Presentation, files: FileList | null }>()
    );

The updatePresentations$ effect is set up like this:

    updatePresentations$ = createEffect(() => {
        return this.actions$
          .pipe(
            ofType(PresentationActions.updatePresentation),
            switchMap(action =>
              this.presentationService.updatePresentation(action.presentation)
                .pipe(
                  tap(presentation => {
                    if (action.files !== null && action.files.length > 0) {
                      this.store.dispatch(PresentationActions.fileUpload({presentationId: presentation.id, files: action.files}));
                    }
                  }),
                  map(presentation => PresentationActions.loadPresentations({pageable: new Pageable()})),
                  catchError(error => of(PresentationActions.updatePresentationFailure({error})))
                )
            )
          );
      });

In essence, my goal is to update the presentation first. Once the presentation is updated, I want to check if there are any files attached and, if so, trigger the fileUpload action. Following that, I intend to reload the presentations by initiating the loadPresentations action (which invokes the loadPresentations$ effect). The fileUpload$ and loadPresentations$ effects are structured as below:

      loadPresentations$ = createEffect(() => {
        return this.actions$.pipe(
          ofType(PresentationActions.loadPresentations),
          concatMap(action => this.presentationService.getPresentations(action.pageable)
            .pipe(
              map(presentations => {
                this.store.dispatch(setLoadingSpinner({status: false}));
                return PresentationActions.loadPresentationsSuccess({page: presentations});
              }),
              catchError(error => of(PresentationActions.loadPresentationsFailure({error})))
            )
          )
        );
      });
      uploadFile$ = createEffect(() => {
        return this.actions$
          .pipe(
            ofType(PresentationActions.fileUpload),
            concatMap(action =>
              this.fileService.uploadFile(action.presentationId, action.files)
                .pipe(
                  map(bool => PresentationActions.loadPresentations({pageable: new Pageable()})),
                  catchError(error => of(PresentationActions.fileUploadFailure))
                )
            )
          );
      });

In the updatePresentations$ effect, you'll notice that I'm attempting to return the loadPresentations action, which should trigger the loadPresentations$ effect. However, this seems to be ineffective, possibly because I need to return an action that will be resolved by the reducer. How can I correct this for it to function correctly?

Answer №1

Don't feel obligated to link your action directly to the reducer. The purpose of actions is to trigger effects that in turn dispatch actions with reducers. Therefore, this approach should work fine.

Your effects appear to be functioning properly, although there may be room for optimization. Aside from that, nothing seems out of place.

  updatePresentations$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PresentationActions.updatePresentation),
      concatMap(action =>
        this.presentationService.updatePresentation(action.presentation).pipe(
          map(presentation => {
            // When fileUpload already triggers loadPresentations, is it necessary to call it again?
            if (action.files !== null && action.files.length > 0) {
              return PresentationActions.fileUpload({ presentationId: presentation.id, files: action.files });
            }
            return PresentationActions.loadPresentations({ pageable: new Pageable() });
          }),
          catchError(error => of(PresentationActions.updatePresentationFailure({ error })))
        )
      )
    );
  });

  uploadFile$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PresentationActions.fileUpload),
      concatMap(action =>
        this.fileService.uploadFile(action.presentationId, action.files).pipe(
          map(bool => PresentationActions.loadPresentations({ pageable: new Pageable() })),
          catchError(error => of(PresentationActions.fileUploadFailure))
        )
      )
    );
  });

  loadPresentations$ = createEffect(() => {
    return this.actions$.pipe(
      ofType(PresentationActions.loadPresentations),
      concatMap(action =>
        this.presentationService.getPresentations(action.pageable).pipe(
          // Consider using switchMap to dispatch multiple actions simultaneously
          switchMap(presentations => [
            setLoadingSpinner({ status: false }),
            PresentationActions.loadPresentationsSuccess({ page: presentations }),
          ]),
          catchError(error => of(PresentationActions.loadPresentationsFailure({ error })))
        )
      )
    );
  });

Similarly,

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

Sending Multiple Data from Multiple Rows in Angular

I am struggling to figure out how to submit an array of data when clicking on multiple rows in Angular. Specifically, I am confused about adding rows and submitting data from those newly added rows. I have been utilizing (ngSubmit) for the submission pro ...

Decipher and comprehend the buttons listed in the language translation document

Looking for assistance with a pipe issue. I've created the following custom SafeHtmlPipe: import { DomSanitizer } from '@angular/platform-browser'; import { Pipe, PipeTransform, SecurityContext } from '@angular/core'; @Pipe({ nam ...

Typescript classes implementing data hydration and dehydration techniques

Exploring ways to share TypeScript classes or interfaces between a React + TS frontend and node + TS backend. Converting class instances into JSON poses a challenge as TS types are removed during compile time. Considering options for defining objects in a ...

I'm currently utilizing CSS GRID to create a map layout, but I'm encountering an issue where the layout is not filling the entire screen. I'm wondering how I can achieve this in Angular

Here is the unique html code snippet for a layout that dynamically creates grids using json input: <!DOCTYPE html> <html lang="en"> <head> <title>Booking Page</title> </head> <body> <div ...

In my attempt to assess the correlation between value 1 and a value in the preceding object, I am utilizing the *ngFor directive

Attempting to compare 2 entries in an *ngFor loop. The code should compare the value at the current object to a value at the previous object. <ng-container *ngFor="let item of s_1.comments[0]; index as b"> <article class="message i ...

Issue with Django and Angular 4 - The requested resource is missing the 'Access-Control-Allow-Origin' header

This is my django code snippet Whenever I test my delete function, this error occurs: The requested resource does not include the 'Access-Control-Allow-Origin' header. This means that the origin is not permitted access. The response resulted ...

Guide on exporting a submodule within a TypeScript package

My aspiration is to develop a Typescript library that emulates the structure of popular libraries like RxJS and Angular Material, which are divided into submodules. RxJS and Angular exhibit a way to import features using syntax like this: // RxJS import ...

Error message: "IAngularStatic type does not have property IScope" caused by Typescript Directives

I'm working on creating an Angular Directive using TypeScript to share a scope item. I created an interface that inherits from ng.IScope, but Visual Studio Code is showing me a warning: "Property IScope does not exist on type IAngularStatic". I am usi ...

Data cannot be transferred to a child element unless it has been initialized during the definition phase

Passing an array data from parent to child component has brought up some interesting scenarios: parent.component.html: <child-component ... [options]="students" > </child-component> Status I: Setting the array on definition ...

Adjusting the margin for a col-md-6 div in Bootstrap 4 to create extra space on the

I am currently developing an Angular application using Bootstrap 4. I am facing an issue where two col-md-6 divs are not appearing side-by-side as expected. The first div includes a table, while the second one displays a white line. Upon inspection, I noti ...

How can I store the data retrieved from an API and then forward it to a URL using Angular?

Is there a way to save and pass the data received from an API to a URL in Angular? SERVICE.ts readonly apiUrl = 'http://localhost:49940/'; constructor(private http: HttpClient) { } getUserName(): Observable<any> { return this.http.ge ...

Unable to log out of OIDC-client due to an error: end session endpoint not found

Currently, I am in the process of setting up a code flow with Auth0 as my chosen identity provider. Successfully, the sign-in process functions well and I receive a valid token from Auth0. However, I am encountering an issue when attempting to sign out ...

Why does Rollup insist on treating my dependency's TypeScript code as if it were written in JavaScript?

I've included an example code snippet here: https://github.com/thejohnfreeman/bugs/commit/b4ff15a670691ada024589693d22f4fd0abae08d The module called parent is primarily composed of type declarations written in TypeScript. The source entrypoint for Ty ...

Tips for incorporating ng2-bootstrap in an Angular2-Meteor1.3 application

Recently, I ran the following commands in my terminal for a new project: npm init meteor add angular2-compilers meteor remove blaze-html-templates meteor npm install --save angular2-meteor meteor npm install --save meteor-node-stubs meteor npm install ...

Having trouble with customizing a selected ListItemButton in Material-UI - need some help with

After reviewing the documentation, I discovered a method to override the styling of the selected class by introducing a new class under .MuiSelected. The implementation looks something like this: const customStyles = makeStyles(() => ({ customizedSele ...

Troubleshooting Node TypeScript with Visual Studio Code using webpack bundling

(In a similar context to this query, but more focused on VsCode) I am attempting to debug the AngularU starter kit with Visual Studio Code. However, it is combining the TypeScript output into one bundle.js along with a side bundle.js.map: ↳web ↳dis ...

Tips for making sure your published npm package respects the baseUrl specified in the tsconfig.json file

I am currently developing an npm library using TypeScript. Within our project configuration, we have specified a baseUrl in our tsconfig.json file. "baseUrl": "src", When referencing files within the src directory, we can simply use: src |-folderA ...

Retrieve select options only upon clicking

Essentially, I have a default value that needs to be loaded into a select element and then make an API call to load the rest only when the select is clicked. <select (click)="getSubevents(market_uri)"> <option *ngFor="let subeven ...

Exploring Rxjs through fundamental queries

Currently, I am working on a small application using Angular 2 and have installed Rxjs 5. However, I have encountered various ways of importing the Rxjs library in tutorials. The code mentioned in the Angular 2 documentation is not functioning properly i ...

What is the process for being directed to the identity server login within an Angular application?

Immediately redirecting users to the identity server upon accessing the application is my goal. Currently, there is a login button that directs users to the ID server with a click, but I want to eliminate this button and have the redirection occur automati ...