Thibs
Thibs

Reputation: 8258

NGRX: TypeError: Actions must have a type property

Being new to ngrx I am facing an exception and not sure why...

I am trying to dispatch an action and handle it in an effect, but I keep getting the error: TypeError: Actions must have a type property

Actions:

export const TEST_ACTION = 'test_action';
export class TryTest implements Action {
    readonly type = TEST_ACTION;

    constructor(public playload: any) {
    }
}
export type MyActions = TryTest;

Effects:

import * as MyActions from "./myactions.actions";

@Injectable()
export class MyEffects {
    @Effect()
    testEffect = this.actions$
        .ofType(MyActions.TEST_ACTION)
        .map((action: MyActions.TryTest) => {
            return 'something'
        });

    constructor(private actions$: Actions) {}
}

Component:

this.store.dispatch(new MyActions.TryTest({ name: 'test' }));

I am using:

effects: 4.0.5 and store: 4.0.3

Upvotes: 12

Views: 21768

Answers (4)

ddc
ddc

Reputation: 965

In my case I have written wrong Action class, Query.action.ts file is having all the actions for the store, in here I have made a silly mistake.

in the line readonly type = QueryActionTypes.SaveQuery; instead of assiging the variable type, I have just defined it.

I have used colon ":" instead of equal "=".

I have written readonly type : QueryActionTypes.SaveQuery;

export enum QueryActionTypes {
 SaveQuery = '[Query] Save Query'
}

export class SaveQuery implements Action {
   readonly type = QueryActionTypes.SaveQuery;
   constructor(public payload: { Query : Query}) {}
}

export type QueryActions = SaveQuery

So ngrx unable to find property type in SaveQuery class (because I have used colon : instead of equal =) which implements Action class. This Action class needs type property

Upvotes: 1

kuceraf
kuceraf

Reputation: 601

by default all effects you create are supposed to emitt an action which is dispatched to the store. Thus, as result from effect function, you need to return type Observable<Action> where Action is an interface from @ngrx/store:

export interface Action {
    type: string;
}

So mapping to object with property type will work:

 @Effect() testEffect = this.actions$
             .ofType(MyActions.TEST_ACTION)
             .map((action: MyActions.TryTest) => {
                    return {type:'action_for_test_effect'}
              });

In this case, you should support action_for_test_effect in your reducer.

If you don't need to dispatch any action from effect, you can disable it by adding config object to effect:

@Effect({dispatch: false}) testEffect = this.actions$
                 .ofType(MyActions.TEST_ACTION);

Upvotes: 1

Engalar Liu
Engalar Liu

Reputation: 51

because effect must return an action at the end. so you have two choices:

  1. return a {type: string} object
  2. return a new Action()

    import * as MyActions from "./myactions.actions";
    
    @Injectable()
    export class MyEffects {
        @Effect()
        testEffect = this.actions$
            .ofType(MyActions.TEST_ACTION)
            .map((action: MyActions.TryTest) => {
                return {type:'your_action'}
            });
    
        constructor(private actions$: Actions) {}
    }
    

Upvotes: 5

Thibs
Thibs

Reputation: 8258

If this helps someone else starting...Turns out I was not returning the Action that ngrx is expecting in the map operator.

Upvotes: 11

Related Questions