How do I register NGRX provideEffects with Angular 17 standalone?

1.3k Views Asked by At

I'm new to Angular 17 and there's really limited docs as to how to use NGRX with new standalone modules or components.

I've installed ngrx effects:

npm install @ngrx/effects

But now because my application doesn't have an app.modules.ts file I'm struggling to use my effects. Here's my app.config.ts

import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideStore } from '@ngrx/store';
import { reducers, metaReducers } from './reducers';
import { provideEffects } from '@ngrx/effects';

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes), provideStore(reducers, { metaReducers }), provideEffects()]
};

https://ngrx.io/api/effects/provideEffects

Here's my effect I'm trying to use:

@Injectable()
export class PrioritiesEffects {
  getPriorities$ = createEffect(() =>
    this.actions$.pipe(
      ofType(PrioritiesActions.getPriorities),
      mergeMap(() => {
        return this.prioritiesService.getPriorities().pipe(
          map((priorities) => PrioritiesActions.getPrioritiesSuccess({ priorities })),
          catchError((error) =>
            of(PrioritiesActions.getPrioritiesFailure({ error: error.message }))
          )
        );
      })
    )
  );

  constructor(private actions$: Actions, private prioritiesService: PrioritiesService) {}
}

In the provideEffects they give an example how to use it with the feature on the router, but I'm unsure how to do that?

import { Routes } from '@angular/router';
import { PrioritiesComponent } from './priorities/priorities.component';

export const routes: Routes = [
  { path: 'priority', component: PrioritiesComponent },
];

How do I register NGRX provideEffects with Angular 17 standalone?

2

There are 2 best solutions below

0
Selaka Nanayakkara On

Try creating seperate app.effects module and try adding it to the main.ts file. Refer the code below :

app.effects.module.ts :

import { NgModule } from '@angular/core';
import { EffectsModule } from '@ngrx/effects';
import { AppEffects } from './app.effects'; // Import your effects

@NgModule({
  imports: [
    EffectsModule.forRoot([AppEffects]),
  ],
})
export class AppEffectsModule { }

In you app.effects.ts :

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { EMPTY } from 'rxjs';
import { mergeMap, catchError, map } from 'rxjs/operators';
import * as MyActions from './my-actions'; // Import your actions

@Injectable()
export class AppEffects {
  loadSomething$ = createEffect(() => this.actions$.pipe(
    ofType(MyActions.loadSomething),
    mergeMap(() => this.myService.getData()
      .pipe(
        map(data => MyActions.loadSomethingSuccess({ data })),
        catchError(() => EMPTY)
      )
    )
  ));

  constructor(
    private actions$: Actions,
    private myService: MyService // Replace with your service
  ) {}
}

In your main.ts:

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app/app.module'; // Import your actual module
import { environment } from './environments/environment';
import { AppEffectsModule } from './app.effects.module'; // Import your effects module

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));


AppEffectsModule; // Make sure to import and include it  module
0
Oleksii Yurchenko On

Do it like this:

export const routes: Routes = [
  {
    path: 'priority',
    component: PrioritiesComponent,
    providers: [provideState(YourFeatureState), provideEffects([PrioritiesEffects])],
  },
];

Read more here https://www.angulararchitects.io/en/blog/routing-and-lazy-loading-with-standalone-components/