How to configure multiple reducers in angular 17 standalone components where ngModule is not present?

481 views Asked by At

I started using angular standalone components and use NgRx state management. I'm trying to set up two slices of the state login and admin login. I created two separate reducers for each. Now, when I'm trying to access using selectors, I cannot access the properties of that state, it says undefined. I think I messed up with the providers in app.config file. I tried many ways, but it's still not working.

This is my first reducer

import { createReducer, on } from "@ngrx/store";
import {
  login,
  loginFailure,
  loginSuccess,
  logout,
  resetLogin
} from "./auth.actions";

export interface LoginState {
  token: string | null,
  error: string | null,
  isLoading: boolean,
  user: any
}

const initialState: LoginState = {
  token: null,
  error: null,
  isLoading: false,
  user: null
}

export const loginReducer = createReducer(
  initialState,
  on(login, (state: LoginState) => ({ ...state , isLoading: true })),
  on(loginSuccess, (state: LoginState, { token, user }) => ({ 
    ...state,
    token,
    user,
    isLoading: false
  })),
  on(loginFailure, (state, { error }) => ({
    ...state,
    error,
    isLoading: false
  })),
  on(logout, () => initialState),
  on(resetLogin, () => initialState)
)

My second reducer

import { createReducer, on } from "@ngrx/store";
import {
  adminLogin,
  adminLoginFailure,
  adminLoginSuccess
} from "./adminAuth.actions";

export interface AdminLoginState {
  error: string | null,
  isLoading: boolean,
  admin: any
}

const initialState : AdminLoginState = {
  error: null,
  isLoading: false,
  admin: null
}

export const adminLoginReducer = createReducer(
  initialState,
  on(adminLogin, (state: AdminLoginState) => ({ ...state , isLoading: true })),
  on(adminLoginSuccess, (state: AdminLoginState, { admin }) => ({
    ...state,
    admin,
    isLoading: false
  })),
  on(adminLoginFailure, (state, { error }) => ({
    ...state,
    error,
    isLoading: false
  })),                                                      
)

I tried setting up provides in app.config file like this -

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser';
import { provideHttpClient, withFetch } from '@angular/common/http';
import {
  StoreModule,
  combineReducers,
  provideState,
  provideStore
} from '@ngrx/store';
import { provideEffects } from '@ngrx/effects';
import { loginReducer } from './states/auth.reducer';
import { LoginEffects } from './states/auth.effects';
import { adminLoginReducer } from './states/adminAuth.reducer';
import { AdminLoginEffects } from './states/adminAuth.effects';
const reducers = combineReducers({
  login: loginReducer,
  adminLogin: adminLoginReducer
});
export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes, withComponentInputBinding()), 
    provideClientHydration(), 
    provideHttpClient(withFetch()), 
    importProvidersFrom(StoreModule.forRoot({
      login: loginReducer,
      adminLogin: adminLoginReducer
    })), 
    provideEffects([LoginEffects, AdminLoginEffects]),
    provideStore(reducers),
    provideState({ name: 'login', reducer: reducers })
  ,]
};
1

There are 1 answers

0
Nafeesath Musfira Badriya On

I've found my solution. I've added an extra provideState with my new reducer. This worked for me.

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes, withComponentInputBinding()), provideClientHydration(), provideHttpClient(withFetch()), 
               provideEffects([LoginEffects,AdminLoginEffects]), provideStore(), provideState({name:'login', reducer: loginReducer}), 
               provideState({name:'adminLogin', reducer: adminLoginReducer})
                ]
};