从NgRX效果更新状态集合/数组的Action和Reducer语法是什么?

时间:2019-09-07 00:33:27

标签: angular ngrx ngrx-effects

我处于NgRX状态:

import { Item } from './item';

export interface FeatureAState {
    items: Item[];
}

然后执行一个操作('[featureA] Add Item'),该操作将Item对象添加到我的商店中的Items数组中。添加每个项目后,我想通过背景效果更新此收藏集。

export const addItem = createAction(
    '[featureA] Add Item',
    (item: Item = { id: 3, title: 'Duff McKagen' }) => ({ item })
);

我创建了一个效果来在化简器添加项目后触发:

updateItems$ = createEffect(() => this.actions$.pipe(
    ofType('[featureA] Add Item'),
    concatMap(() => this.myService.doSomeWork()
        .pipe(
            map(updatedItems => ({ type: '[featureA] Updated', payload: updatedItems }))
        ))
));

据我了解,这需要myService.doSomeWork()返回一个Observable吗?现在,我已经将返回值硬编码为从新数组创建的Observable,因此,我希望一旦效果完成并且'[featureA] Updated'操作由减速器。

export class MyserviceService {

  doSomeWork() {
    return of([{ id: 6, title: 'Peter Parker' }]);
  }
}

所以我现在需要一个动作来处理效果结果并更新商店?但是我不知道如何为此编写Action或Reducer。

export const updatedItems = createAction(
    '[featureA] Updated',
    props<{ items: Item[] }>()
);

// Also tried...

export const updatedItems = createAction(
    '[featureA] Updated',
    (items: Item[]) => ({ items }) // don't understand what I'm doing here, but I guess this action needs to pass through the output of `myService.doSomeWork()` (an Observable mapped to an Action via concatMap()?) for the Reducer to handle?
);
on(updatedItems, (state, { updatedItems }) => ({
    ...state,
    items: updatedItems // I suspect this is not correct, or the 'updatedItems' action is not passing through the correct object
}))

The error I seem to be getting is `ERROR in src/app/featureA/state/featureA.reducer.ts(11,32): error TS2339: Property 'updatedItems' does not exist on type '{ items: Item[]; } & TypedAction<"[featureA] Updated"> & { type: "[featureA] Updated"; }'.`

2 个答案:

答案 0 :(得分:0)

您应该使用updatedItems而不是items,因为您是在操作有效载荷中传递它的。

on(updatedItems, (state, { items }) => ({
    ...state,
    items
}))

答案 1 :(得分:0)

问题似乎出在这里:

updateItems$ = createEffect(() => this.actions$.pipe(
    ofType('[featureA] Add Item'),
    concatMap(() => this.myService.doSomeWork()
        .pipe(
            map(updatedItems => ({ type: '[featureA] Updated', payload: updatedItems })) // <= HERE
        ))
));

我不知道payload只是我的行为的财产,不必称为payload。因为当时我正在将“有效负载”传递给操作,但没有在操作或减速器中引用它。实际上,我也没有必要在Action中引用它。因此,这将根据我的服务响应来更新商店:

export const updatedItems = createAction(
    '[featureA] Updated'
);
on(updatedItems, (state, { payload }) => ({
    ...state,
    items: payload
}))

这将是

updateItems$ = createEffect(() => this.actions$.pipe(
    ofType('[featureA] Add Item'),
    concatMap(() => this.myService.doSomeWork()
        .pipe(
            map(updatedItems => ({ type: '[featureA] Updated', items: updatedItems }))
        ))
));
on(updatedItems, (state, { items }) => ({
    ...state,
    items
}))

我遇到Typescript错误,可以通过使用以下任意一种更新Action来解决:

export const updatedItems = createAction(
    '[featureA] Updated',
    props<{ items: Item[] }>()
);

// or

export const updatedItems = createAction(
    '[featureA] Updated',
    (items: Item[]) => ({ items })
);

最后我已经讲完了,这似乎更清楚了发生了什么:

updateItems$ = createEffect(() => this.actions$.pipe(
    ofType('[featureA] Add Item'),
    concatMap(() => this.myService.doSomeWork()
        .pipe(
            map(updatedItems => ({ type: '[featureA] Updated', payload: updatedItems }))
        ))
));
export const updatedItems = createAction(
    '[featureA] Updated',
    (payload: Item[]) => ({ payload })
);
on(updatedItems, (state, { payload }) => ({
    ...state,
    items: payload
}))