1

I am migrating my Angular application, v20, which uses ng/rx store from module based to standalone.

I had chosen to use classes for most of my reducers. For example, I have a reducer as follows

@Injectable({ providedIn: 'root' }) export class AppReducer { private readonly initialState: AppState = { networkTestModeEnabled: false, networkTestOnline: true }; /** * Reducer function */ public reduce = createReducer( this.initialState, on(appActions.setTestNetworkMode, (state, { testModeEnabled }): AppState => ({ ...state, networkTestModeEnabled: testModeEnabled })), on(appActions.setTestNetworkOnline, (state, { isOnline }): AppState => ({ ...state, networkTestOnline: isOnline })), ); } 

And in my app.module.ts I could use this via an InjectionToken...

export const APP_REDUCER_TOKEN = new InjectionToken<ActionReducer<Map<string, AppState>>>('App reducer'); export function appReducerFactory(reducer: AppReducer): (state: AppState, action: Action) => AppState { return (s, a) => reducer.reduce(s, a); } 

And then in the module have a setup like the following...

StoreModule.forRoot({}), EffectsModule.forRoot([]), StoreModule.forFeature(Constants.vals.featureNames.appState, APP_REDUCER_TOKEN), StoreModule.forFeature(Constants.vals.featureNames.globalfeature1, F1_TOKEN), EffectsModule.forFeature([ AppEffects, F1Effects, .. etc ]), { provide: APP_REDUCER_TOKEN, deps: [AppReducer], useFactory: appReducerFactory, }, 

Now going to standalone, in my main.ts, I see I should be using the provideStore, provideEffects and provideState, so I have...

bootstrapApplication(AppComponent, { providers: [ provideStore(), provideEffects([AppEffects, F1Effects]), provideState({ name: Constants.vals.featureNames.appState, reducer: APP_REDUCER_TOKEN, }), provideState({ name: Constants.vals.featureNames.F1, reducer: F1_REDUCER_TOKEN, }), 

However, I am getting the following error for the line

provideState({ name: Constants.vals.featureNames.appState, reducer: APP_REDUCER_TOKEN, }), 

enter image description here

I have another reducer that is NOT a class, and not using an InjectionToken, and this is accepted, but not where I use the token.

My question is, how do I now setup a reducer that is defined as a class? Do we still use an InjectionToken, and/or if so, how do I use this with provideState?

[UPDATE1]

Unfortunately using @Naren Murali method I get the error...

app-events.effects.ts:164 ERROR RuntimeError: NG0203: The `AppReducer` token injection failed. `inject()` function must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`. Find more at https://angular.dev/errors/NG0203 at reducer (app.config.ts:92:31) 

This is weird as the app-events.effects,ts is not even for the AppReducer. it is for a different feature. My AppState does not have any effects (but other slices do)

i.e I also have

provideEffects([CurrentDayEffects, AppEventsEffects]), 

etc

1 Answer 1

1

The below approach seems to work fine. I have access to Dependency injection also.

bootstrapApplication(AppComponent, { providers: [ provideStore(), provideEffects([AppEffects, F1Effects]), provideState({ name: Constants.vals.featureNames.appState, reducer: (state: any | undefined, action) => { const reducer = inject(AppReducer); return reducer.reduce(state, action); }, }), provideState({ name: Constants.vals.featureNames.F1, reducer: F1_REDUCER_TOKEN, reducer: (state: any | undefined, action) => { const reducer = inject(AppReducer); return reducer.reduce(state, action); }, }), ... 

Making NGRX Features Reusable

Sign up to request clarification or add additional context in comments.

2 Comments

Awesome, I did the above, and no more IDE errors. I cant quite run yet, so I will carry on and come back once I confirm it works (and set this as the answer)!
I finally have got the app converted all to standalone, so I can run it again. I am having issues with the above approach. I have my AppReducer decared as you do above, and get no build errors, however when I run I get Angular is running in development mode. app-events.effects.ts:164 ERROR RuntimeError: NG0203: The AppReducer` token injection failed. inject() function must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.