【问题标题】:Why is my @Effect overwriting existing state with ngrx in Angular 6?为什么我的@Effect 在Angular 6 中用ngrx 覆盖现有状态?
【发布时间】:2018-08-03 15:15:55
【问题描述】:

我在 Angular 6 应用程序中使用 ngrx,我可以成功地从数据库加载数据并将其显示在屏幕上。但是,当我导航到应用程序中的新页面然后返回时,不会保留状态,并且似乎再次调用 @Effect 并再次从数据库加载数据。这是我的代码:

效果

export class ProductEffects {
    constructor(private productService: ProductService, private actions$: Actions) { }

    @Effect()
    loadProducts$: Observable<Action> = this.actions$.pipe(
        ofType(productActions.LOAD_ACTION),
        switchMap(action =>
            this.productsService.getProductDetails().pipe(
                map(product => new productActions.LoadSuccess(product)),
                catchError(err => of(new productActions.LoadError(err)))
            )
        )
    );

减速器

export interface ProductState {
    product: Product;
}

const initialState: ProductState = {
    product: {}
};

export function reducer(state = initialState, action: Action) {
    switch (action.type) {
        case SET_PRODUCT:
            return { ...state, product: (action as SetProductAction).payload };

        case LOAD_SUCCESS:
            return { ...state, product: (action as LoadSuccess).payload, error: '' };

        default: return state;
    }
}

操作

export const SET_PRODUCT = '[Product] Set Product';
export const LOAD = '[Product] Load';
export const LOAD_SUCCESS = '[Product] Load Success';
export const LOAD_ERROR = '[Product] Load Error';

export class SetProductAction implements Action {
    readonly type = SET_PRODUCT;
    constructor(public payload: Product) { }
}

export class Load implements Action {
    readonly type = LOAD;
}

export class LoadSuccess implements Action {
    readonly type = LOAD_SUCCESS;
    constructor(public payload: Product) { }
}

export type ProductActions = SetProduct | Load | LoadSuccess;

商店

export interface State extends fromRoot.AppState {
    product: fromProduct.ProductState;
}

// selectors
const getProductState = createFeatureSelector<fromProduct.ProductState>('product');

export const getProduct = createSelector(
    getProductState,
    state => state.product
}

组件

products$: Observable<Product>;

constructor(private store: Store<fromProduct.State>) { }

ngOnInit() {
    this.store.dispatch(new Load());
    this.products$ = this.store.pipe(select(fromProduct.getProduct));
}

【问题讨论】:

  • 如果是loaded,则您没有resolverguard 来处理,所以据我所知,这是基于您的代码sn-p 的预期行为。跨度>

标签: javascript angular ngrx ngrx-effects


【解决方案1】:

您的 ngrx 实现对我来说似乎一切正常。您所描述的是绝对正常的行为。一旦您离开页面,组件就会被销毁并创建新组件,即调用 ngOnInit。如果将加载逻辑放在 ngOnInit 中,则每次导航到此页面时都会加载状态。

【讨论】:

  • 我想我明白了。在我的@Effect 中,它在我的switchMap 之前添加了take(1) RxJS 运算符。它似乎已经解决了这个问题,状态从一个特征到另一个特征,从一个页面到另一个页面。
  • 是的,在这种情况下这是可能的。我认为缺点是,我认为调度第二个加载动作(可能稍后)将没有效果。
  • 我在我的开发工具中看到每次返回页面时都会调用 Load 操作,并保留状态。目前我只做一次加载,但会看看第二次加载是否什么都不做。
  • 我有一个应用程序,一旦加载了应用程序/模块,我就会在其中调度加载操作。这将在后台异步发生。一旦用户导航到组件,数据就已经存在,因此他/她不必等到数据加载完毕。
  • 我也想过。我的应用程序正在使用延迟加载,所以我很可能会将此加载效果放在功能组件中,然后每当遇到该功能时,数据就已经存在了。与在 App Load 中执行此操作的概念相同。谢谢:-)
猜你喜欢
  • 2021-01-28
  • 1970-01-01
  • 2019-06-14
  • 1970-01-01
  • 1970-01-01
  • 2020-01-22
  • 2020-01-15
  • 2020-11-18
  • 2019-02-11
相关资源
最近更新 更多