【问题标题】:Store subscribe is not called with ngrx store 4使用 ngrx 存储 4 不调用存储订阅
【发布时间】:2023-03-18 07:02:02
【问题描述】:

在我的 Angular (4) 应用程序中,我想使用 ngrx 4 引入减速器/状态管理。

我有一个主模块

@NgModule({
    imports: [
        // ...
        StoreModule.forRoot({}),
        EffectsModule.forRoot([])
    ],

    declarations: [
        AppComponent
    ],

    bootstrap: [AppComponent]
})

还有一个延迟加载的模块

@NgModule({
    imports: [
        StoreModule.forFeature('lazy', {
            items: itemsReducer
        }),
        EffectsModule.forFeature([ItemEffects])
    ],

    declarations: [
        // Components & Directives
    ]
})

这是我的减速器

export function itemsReducer(state: Item[] = [], action: ItemAction<any>) {
    switch (action.type) {

        case ADD:
            return [action.payload, ...state];

        case DELETE:
            return state.filter((item) => item.id !== action.payload.id);

        case ITEMS_LOADED:
            return Object.assign([], action.payload);

        case LOAD_ITEMS:
            return state;

        default:
            return state;
    }
}

我也在处理这样的效果:

@Injectable()
export class ItemEffects {

    @Effect() addItem$: Observable<Action> = this.actions$.ofType(ADD)
        .mergeMap((payload: any) =>
            this.dataService.addItem(payload)
                // If successful, dispatch success action with result
                .map((data: any) => {
                    return createLoadItemsAction();
                })
                // If request fails, dispatch failed action
                .catch(() => of({ type: 'FAILED' }))
        );

    @Effect() loadItems$: Observable<Action> = this.actions$.ofType(LOAD_ITEMS)
        .mergeMap(() =>
            this.dataService.getAllItems()
                // If successful, dispatch success action with result
                .map((data: Item[]) => (createItemsLoadedAction(data)))
                // If request fails, dispatch failed action
                .catch(() => of({ type: 'FAILED' }))
        );

    constructor(
        private dataService: DataService,
        private actions$: Actions
    ) { }
}

在我的有状态组件中,我像这样订阅这个商店

export class MainItemsComponent implements OnInit {
    items: Observable<Items[]>;

    constructor(private store: Store<any>) {
        this.items = this.store.select('items');
    }

    ngOnInit() {
        this.store.dispatch(createLoadItemsAction());
    }

    // ...

}

使用console.logs,我可以看到效果正在工作,使用正确的操作“ITEMS_LOADED”调用reducer,所有项目都在里面,但它们没有传递给我的有状态组件并且没有显示。

我的动作是这样的

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

export interface ItemAction<T> extends Action {
    payload?: T;
}

/*
 * action types
 */

export const ADD = 'ADD'
export const DELETE = 'DELETE'
export const LOAD_ITEMS = 'LOAD_ITEMS'
export const ITEMS_LOADED = 'ITEMS_LOADED'

/*
 * action creators
 */

export function createAddItemAction(item: Item): ItemAction<Item> {
    return { type: ADD, payload: item }
}

export function createDeleteItemAction(item: Item): ItemAction<Item> {
    return { type: DELETE, payload: item }
}

export function createItemsLoadedAction(items: Item[]): ItemAction<Item[]> {
    return { type: ITEMS_LOADED, payload: items }
}

export function createLoadItemsAction(): ItemAction<Item> {
    return { type: LOAD_ITEMS }
}

我正在使用

 "@ngrx/effects": "^4.0.5",
 "@ngrx/store": "^4.0.3",

我错过了什么?我的目标是在加载组件时加载项目。

【问题讨论】:

  • 使用ItemAction 类文件更新帖子
  • 您如何测试this.items = this.store.select('items') 不起作用的事实?如果您可以显示您的模板,因为错误可能在那里
  • 很难看到这样的问题,如果你能复制一个小的 plunker 会更好。有关ngrx的更多信息,请查看link

标签: angular ngrx ngrx-store ngrx-effects


【解决方案1】:

嗯。如果我理解正确,选择另一种方式。

你现在期待什么? this.store.select('items') 这应该如何工作?

据我了解,您需要创建选择器。我不确定您是否创建了它们,因为我在您提供的代码中看不到它们中的任何一个。而且你还以一种奇怪的方式使用select

我认为,您缺少选择器。你需要这个:

  • 创建选择器示例:here
  • 使用选择器示例:here

或者您能否解释一下您对当前代码的期望? :) 也许我什么都不知道。

【讨论】:

    【解决方案2】:

    要获取数据,您需要使用选择器并添加上面 A. Moynet 提到的状态

    https://ngrx.io/guide/store/selectors

    ngrx 的例子是

    import { createSelector } from '@ngrx/store';
    
    export interface FeatureState {
      counter: number;
    }
    
    export interface AppState {
      feature: FeatureState;
    }
    
    export const selectFeature = (state: AppState) => state.feature;
    
    export const selectFeatureCount = createSelector(
      selectFeature,
      (state: FeatureState) => state.counter
    );
    

    为了使用它,我们在组件中这样做

    ngOnInit() {
        this.counter = this.store.pipe(select(fromRoot.selectFeatureCount))
    }
    

    【讨论】:

      【解决方案3】:

      尝试定义 AppState 接口并输入 store 的状态:

      interface AppState{
        items: Item[]
      }
      
      constructor(private store: Store<AppState>)
      

      然后不要忘记在模板文件中异步管道(items | async)或在组件文件中订阅(但我想你知道)

      【讨论】:

        猜你喜欢
        • 2020-05-22
        • 1970-01-01
        • 2019-08-18
        • 2017-06-24
        • 2022-01-20
        • 2019-12-04
        • 2012-05-29
        • 1970-01-01
        • 2020-08-15
        相关资源
        最近更新 更多