georgio bou sleimen
georgio bou sleimen

Reputation: 31

Why the Actions object from NgRx effects cannot be injected despite including the necessary module and no circular dependency?

So I'm working on a colaborative document editor application and I'm using NgRx effects here to induce a state change based on another state change. I've installed the package, configured the app.config file to include EffectsModule but still I'm getting an error and because of it my application is not running.

TypeError: Cannot read properties of undefined (reading 'pipe')
    at effects.ts:14:19
    at createEffect (ngrx-effects.mjs:85:47)
    at <instance_members_initializer> (effects.ts:13:21)
    at new _FeatureEffects (effects.ts:9:3)
    at Object.FeatureEffects_Factory [as factory] (effects.ts:31:6)
    at core.mjs:3132:35
    at runInInjectorProfilerContext (core.mjs:866:5)
    at R3Injector.hydrate (core.mjs:3131:11)
    at R3Injector.get (core.mjs:3005:23)
    at injectInjectorOnly (core.mjs:1095:36)

Effects Class:

import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { of } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';
import { addDocumentSuccess, loadDocumentsSuccess, loadDocumentsFailure } from './actions';

@Injectable()
export class FeatureEffects {
  constructor(private actions$: Actions) {
    console.log(this.actions$); // Verify if `actions$` is initialized correctly
  }

  triggerAction2$ = createEffect(() => 
    this.actions$.pipe(
      ofType(addDocumentSuccess),
      switchMap((action) => {
        const result = action.documents;

        // Ensure result is not undefined or null
        if (result) {
          return of(loadDocumentsSuccess({ documents: result }));
        } else {
          console.error('No documents found in action');
          return of(loadDocumentsFailure({ error: 'No documents found' })); // Dispatch an error action if needed
        }
      }),
      catchError(error => {
        console.error('Error in effect:', error);
        return of(loadDocumentsFailure({ error: 'An error occurred' })); // Dispatch an error action
      })
    )
  );

  
  
}

app.config :

import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
import { StoreModule } from '@ngrx/store';
import { routes } from './app.routes';
import { addDocumentReducer, documentLoadReducer, documentProcessedReducer, LoginReducer } from './NgRx/reducer';
import { httpInterceptor } from './http.interceptor';
import { environment } from './environment';
import { EffectsModule } from '@ngrx/effects';
import { FeatureEffects } from './NgRx/effects';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideAnimations(),
    provideHttpClient(withInterceptors([httpInterceptor])),

    // Importing Store and Effects at the root level
    importProvidersFrom(
      StoreModule.forRoot({
        loginState: LoginReducer,
        documentProcessedState: documentProcessedReducer,
        documentLoadingState: documentLoadReducer,
        addDocumentState: addDocumentReducer,
      }),
      // Add EffectsModule.forRoot() for initializing root effects
      
      EffectsModule.forRoot([FeatureEffects]), // Root effects can be provided here if any
      StoreDevtoolsModule.instrument({
        maxAge: 25, // Retains last 25 states
        logOnly: environment.production, // Restrict extension to log-only mode
      })
      // Add your feature effects here
      
    )
  ]
};

I tried to include both EffectsModule.forRoot and .forModule with thecorrespondnig class and after Store.Module ( I've searched that it is necessary to include after) . I debugged the code and I'm 100% sure the source is actions$ whioch is an object of type Actions cannot be injected. Again one root cause could be circular dependencies, but I've run a command that checks for ones and it didn't . So I'm way too confused and impotent of finding the error.

Upvotes: 2

Views: 343

Answers (3)

user2325149
user2325149

Reputation: 64

Experienced the same bug working with Angular 19 and NGRX 19. I resolved it using the inject() instead of the constructor() method.

private actions$ = inject(Actions)

Instead of

constructor(private actions$: Actions) {}

Upvotes: 2

Kmaczek
Kmaczek

Reputation: 648

Go to the stack blitz Fabio mentioned Link . Copy tsconfig.json, there is a chance it will show you more errors, hidden before. In my case there was somehing wrong with path, error didn't mentioned what.

Turns out, you can't use: user.effects.ts, so I renamed to user-effects.ts. Only then it worked for me.

Upvotes: 0

The Fabio
The Fabio

Reputation: 6250

You probably have not configured the root imports properly. Or maybe your reducers are missing something.

Here is a stackblitz showing your example works fine...

Upvotes: 0

Related Questions