Reputation: 8258
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
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
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
Reputation: 51
because effect must return an action at the end. so you have two choices:
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
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