Search code examples
angulartypescriptngrxngrx-store

Custom NgRx Action seems to be not working in angular 11


I am trying to create a simple application to better understand how NgRx works. For that i have developed the following code. But it is not working as expected.

My Action.ts:

import { Action } from '@ngrx/store';
import { Employee } from '../Employee.model';

export const ADD_EMPLOYEE = 'ADD_EMPLOYEE';
export const EDIT_EMPLOYEE = 'EDIT_EMPLOYEE';


export class AddEmployee implements Action {
    readonly type = ADD_EMPLOYEE;
    constructor(public payload: Employee){}
}

export class EditEmployee implements Action {
    readonly type = EDIT_EMPLOYEE;
    // constructor(public payload: Employee){}
}

export type EmployeeAction = EditEmployee | AddEmployee;

My reducer.ts

import * as EmployeeActions from './employee.actions';

const initialState = {
    states: [
        {name: 'Arizona', code: 'Arizona'},
        {name: 'California', value: 'California'},
        {name: 'Florida', code: 'Florida'},
        {name: 'Ohio', code: 'Ohio'},
        {name: 'Washington', code: 'Washington'}
    ],
    
};
export function employeeReducer (state = initialState, action: EmployeeActions.EmployeeAction) {

    switch(action.type) {
        case EmployeeActions.ADD_EMPLOYEE:
            console.log("Employee reducer called: ", action.payload);
            return {
                ...state,
                
            };
        default:
            return state;

    }
}

My app.module.ts:

import { StoreModule } from '@ngrx/store';
.....

imports: [
    BrowserModule,
    BrowserAnimationsModule,
    StoreModule.forRoot({employeeStoreReducer: employeeReducer})
  ],

at this point i am getting the following error:

error TS2322: Type '(state: { states: ({ name: string; code: string; value?: undefined; } | { name: string; value: string; code?: undefined; })[]; } | undefined, action: EmployeeAction) => { states: ({ name: string; code: string; value?: undefined; } | { ...; })[]; }' is not assignable to type 'ActionReducer<{ states: ({ name: string; code: string; value?: undefined; } | { name: string; value: string; code?: undefined; })[]; }, Action>'.
  Types of parameters 'action' and 'action' are incompatible.
    Type 'Action' is not assignable to type 'EmployeeAction'.
      Property 'payload' is missing in type 'Action' but required in type 'AddEmployee'.

36     StoreModule.forRoot({employeeStoreReducer: employeeReducer}),
                           
  src/app/employee/store/employee.actions.ts:10:17
    10     constructor(public payload: Employee){}

    'payload' is declared here.

But if i change action: EmployeeActions.EmployeeAction to action: Action it starts working. But in this case i cannot send any payload. Please help in resolving the issue and also let me know the reason for this. I can share more code if needed. I am using angular version 11.1.2, ngrx version 11.0.1. Thanks in advance.


Solution

  • If this project is using Angular/NGRX v11.x, and you are attempting to learn modern techniques with NGRX, I would discard the pattern you are using and use the factory functions provided by the library.

    For example:

    Action File

    export const addEmployee = createAction(
      ADD_EMPLOYEE, 
      props<{payload: Employee}>()
    );
    export const editEmployee = createAction(
      EDIT_EMPLOYEE, 
      props<{payload: Employee}>()
    );
    

    Reducer File

    export const reducer = createReducer(
      initialState,
      
      on(EmployeeActions.addEmployee, (state, { payload }) => {
        console.log("Employee Reducer Called")
        return {
           ...state, //Insert Add Logic here
        };
      }),
    
      on(EmployeeActions.editEmployee, (state, { payload }) => {
        console.log("Employee Reducer Called")
        return {
           ...state, //Insert Edit Logic here
        };
      }),
    );
    

    The NGRX Docs show this effectively: https://ngrx.io/guide/store/reducers