I am using Angular 18 and ngRx.
I wrote a following effect:
import {Injectable} from '@angular/core';
import {Actions, createEffect, ofType} from '@ngrx/effects';
import * as PostsActions from '../actions/actions';
import {catchError, map, mergeMap, of} from 'rxjs';
import {PostService} from '../services/postService';
@Injectable()
export class PostEffects {
constructor(private actions$: Actions, private postService: PostService) {
console.log("Constructor");
}
getPosts$ = createEffect(() => {
console.log("Effect Creation")
return this.actions$.pipe(
ofType(PostsActions.getPosts),
mergeMap(() => {
return this.postService.getPosts().pipe(
map(posts => posts.posts),
map((allPosts) => PostsActions.getPostsSuccess({posts: allPosts})),
catchError((error) =>
of(PostsActions.getPostsFailure({error: error.message}))
)
);
})
)
}
);
}
and I registered it in this way:
import {ApplicationConfig, isDevMode, provideZoneChangeDetection} from '@angular/core';
import {provideRouter} from '@angular/router';
import {routes} from './app.routes';
import {provideStore} from '@ngrx/store';
import {provideStoreDevtools} from '@ngrx/store-devtools';
import {reducers as postSlice} from './reducers/reducers';
import {provideEffects} from '@ngrx/effects';
import {PostEffects} from './effects/effects';
export const appConfig: ApplicationConfig = {
providers: [
provideZoneChangeDetection({eventCoalescing: true}),
provideRouter(routes),
provideStore({ postSlice }),
provideStoreDevtools({maxAge: 25, logOnly: !isDevMode(), autoPause: true}),
provideEffects([PostEffects])
]
};
The problem which I have is that constructor is not called before getPosts$ = createEffect(() => { ... });
It leads to situation where my properties are not initialized.
The statement from: console.log("Constructor");
is not printed.
Basically when you use ES2022
in the target of tsconfig.json
you will face this problem. The code defined might be trying to access a property before the constructor is initialized.
To solve this you can either set the property "useDefineForClassFields": false
to solve the problem.
You can check the two github issues below to find the solution to this problem.
Github issue - Cannot read properties of undefined (reading 'pipe') #3698
export class PostEffects {
getPosts$;
constructor(private actions$: Actions, private postService: PostService) {
this.getPosts$ = createEffect(() => {
return this.actions$.pipe(
...
)
}
);
}
}
inject
to define actions$ first and then initialize the property:export class PostEffects {
private actions$ = inject(Actions);
getPosts$ = createEffect(() => {
return this.actions$.pipe(
...
)
}
);
...
}
inject
rather than using the property actions$
:export class PostEffects {
getPosts$ = createEffect(() => {
return inject(Actions).pipe(
...
)
}
);
...
}