問題描述
Angular NgRx 效果,如何傳遞參數? (Angular NgRx effects, how to pass a parameter?)
我正在嘗試將 id 參數從調度發送到效果,我在谷歌中找不到這種情況的任何示例。
這是我已經擁有的代碼:
組件:
ngOnInit(): void {
this.packageClass = `type‑${this.package.packageType.toLowerCase()}`;
// I set the payload to the action
this.store.dispatch(new LoadClusterInfo({id: this.package.id}));
this.checkStatus();
}
效果(我需要訪問值的地方)
@Effect()
getClusterInfo =
this.actions.ofType(resultActions.Type.LOAD_CLUSTER_INFO)
.pipe(
switchMap(() => {
let id = 'HARDCODED_ID';
return this.service.getPackageCluster(id); // Here is where i need the value
}),
map((packageCluster: PackageCluster) => new LoadClusterInfoSuccess(packageCluster)),
catchError((err: Error) => of(new LoadClusterInfoError(err))),
);
最後一個動作:
export class LoadClusterInfo implements Action {
readonly type = Type.LOAD_CLUSTER_INFO;
constructor(readonly payload: any) {}
}
如何訪問id由組件(this.package.id)發送的效果?
參考解法
方法 1:
You can access the action's payload property in the switchMap
operator. A couple of extra things:
- Use the pipeable
ofType
operator because theofType
function is removed in NgRx 7 - Type the
ofType
operator to have a typed action - use
map
andcatchError
on the service stream, otherwise when an error occurs the effect stream will get destroyed. See the NgRx docs for more info.
</ul>
@Effect()
getClusterInfo = this.actions
.pipe(
ofType<LoadClusterInfo>(resultActions.Type.LOAD_CLUSTER_INFO),
switchMap((action) => {
return this.service.getPackageCluster(action.id).pipe(
map((packageCluster: PackageCluster) => new LoadClusterInfoSuccess(packageCluster)),
catchError((err: Error) => of(new LoadClusterInfoError(err))),
);
}),
);
Update NgRx v8 +
With createAction
and createEffect
, the action is automatically inferred so you can do this and benefit from the types:
getClusterInfo = createEffect(() => {
return this.actions.pipe(
ofType(loadClusterInfo),
switchMap((action) => {
return this.service.getPackageCluster(action.id).pipe(
map((packageCluster: PackageCluster) => new LoadClusterInfoSuccess(packageCluster)),
catchError((err: Error) => of(new LoadClusterInfoError(err))),
);
}),
)
}
方法 2:
For those trying to get params with mergeMap you can do it like these:
loadItems$ = createEffect(() =>
this.actions$.pipe(
ofType(YOUR_ACTION_NAME),
mergeMap((action) =>
this.myService.getAll(action.parameters).pipe(
map((items) => ({
type: ITEMS_LOADED_SUCESSFULLY,
items: itemsList,
})),
catchError(() => EMPTY)
)
)
)
);
To dispatch the action:
this.store.dispatch(loadItems({ parameters: parameter }))
And in your .actions.ts:
export const loadItems = createAction(
YOUR_ACTION_NAME, props<{ parameters: string }>());
(by nperez9、timdeschryver、Dylan Moguilevsky)