When I include provideEffects(ConfigEffects)
in main/ts -> app.config.ts
,
I got the following error
TypeError: this.actions$ is undefined
ConfigEffects config.effects.ts:23
createEffect Angular
ConfigEffects config.effects.ts:20
_ConfigEffects config.effects.ts:13
ConfigEffects_Factory main.js:70
Angular 18
<anonymous> main.ts:5
Why this.actions$ is not injected ? Am I missing any configurations ? Any help would be appreciated ? Please let me know if any more details are required
I have a configuration in my public/config/config.json
as follows
{
"auth0": {
"domain": "xxxx.us.auth0.com",
"clientId": "xxxxx",
"redirectUri": "http://localhost:4200",
"logoutRedirectUri": "http://localhost:4200",
"audience": "https://xxxxx/"
}
}
My main.ts -> app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideHttpClient(),
provideStore({ config: configReducer }),
provideEffects(ConfigEffects)
]
};
app.component.ts
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
config$: Observable<any>;
constructor(private store: Store) {
this.config$ = this.store.select(selectConfig);
}
ngOnInit(): void {
this.store.dispatch(loadConfig());
}
}
config.effect.ts
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { ConfigService } from './config.service';
import * as ConfigActions from './config.actions';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { of } from 'rxjs';
@Injectable()
export class ConfigEffects {
constructor(
private actions$: Actions,
private configService: ConfigService
) {
console.log('Actions:', this.actions$);
console.log('ConfigService:', this.configService);
}
loadConfig$ = createEffect(() =>
{console.log('loadConfig...');
return this.actions$.pipe(
ofType(ConfigActions.loadConfig),
mergeMap(() =>
this.configService.loadConfig().pipe(
map((config) => ConfigActions.loadConfigSuccess({ config })),
catchError((error) => of(ConfigActions.loadConfigFailure({ error })))
)
)
)
}
);
}
In the previous code, the loadConfig$
is initialized before the actions$
has a value, hence you might get this issue.
One way to solve this might be to set "useDefineForClassFields": false
in the tsconfig.json
, if you are using ES2022
.
You can also try inject
before the loadConfig$
is defined, so that actions$
is always available.
import { Injectable, inject } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { ConfigService } from './config.service';
import * as ConfigActions from './config.actions';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { of } from 'rxjs';
@Injectable()
export class ConfigEffects {
actions$: Actions = inject(Actions);
loadConfig$ = createEffect(() => {
console.log('loadConfig...');
return this.actions$.pipe(
ofType(ConfigActions.loadConfig),
mergeMap(() =>
this.configService.loadConfig().pipe(
map((config) => ConfigActions.loadConfigSuccess({ config })),
catchError((error) => of(ConfigActions.loadConfigFailure({ error })))
)
)
);
});
constructor(private configService: ConfigService) {
console.log('Actions:', this.actions$);
console.log('ConfigService:', this.configService);
}
}