2

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.

enter image description here

The statement from: console.log("Constructor"); is not printed.

1 Answer 1

4

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

Github issue - Pre-initialized class fields with a TSConfig target set to ES2022 with useDefineForClassFields set to true will cause runtime issues #3654

Possible Fixes:


Initialize the property value inside the constructor:

export class PostEffects { getPosts$; constructor(private actions$: Actions, private postService: PostService) { this.getPosts$ = createEffect(() => { return this.actions$.pipe( ... ) } ); } } 

use inject to define actions$ first and then initialize the property:

export class PostEffects { private actions$ = inject(Actions); getPosts$ = createEffect(() => { return this.actions$.pipe( ... ) } ); ... } 

Inject the actions directly using inject rather than using the property actions$:

export class PostEffects { getPosts$ = createEffect(() => { return inject(Actions).pipe( ... ) } ); ... } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.