angular - ngrx 8 : Access state of @ngrx/data entity from reducer function

标签 angular ngrx ngrx-store ngrx-store-8.0 ngrx-data

我需要在reducer函数中访问ngrx/data实体的状态。

我正在构建一个寻呼机(分页),用户可以在其中导航到最后一页以及其他选项。但我不知道缓存中有多少项,EntitySelectorsFactory 会执行 (selectCount),但我不想获取组件中的数据,并且使用 props 来传递它们,而不是它们应该在 reducer 中。

或者也许有更好的方法。

行动

import {createAction, props} from '@ngrx/store';

export const toStart = createAction('[Pager] To Start');
export const toEnd = createAction('[Pager] To End');
export const incrementPage = createAction('[Pager] Increment');
export const decrementPage = createAction('[Pager] Decrement');
export const setPage = createAction('[Pager] Set', props<{page: number}>());
export const setPageSize = createAction('[Pager] Set Page Size', props<{size: number}>());

reducer

import { Action, createReducer, on } from '@ngrx/store';
import * as PagerActions from '../actions/pager';
import {EntitySelectorsFactory} from '@ngrx/data';
import {Rant} from '../models/rant';

export const pagerFeatureKey = 'pager';

export interface State {
  page: number;
  pageSize: number;
}

export const initialState: State = {
  page: 1,
  pageSize: 10,
};

const rantSelectors = new EntitySelectorsFactory().create<Rant>('Rant');

const pagerReducer = createReducer(
  initialState,
  on(PagerActions.toStart, state => ({...state, page: 1})),
  on(PagerActions.toEnd, state => ({...state, page: Math.floor(rantSelectors.selectEntities.length / state.pageSize)})),
  on(PagerActions.setPage, (state, action) => ({...state, page: action.page})),
  on(PagerActions.incrementPage, state => ({...state, page: state.page + 1})), // TODO: check if out of bounds
  on(PagerActions.decrementPage, state => ({...state, page: state.page > 1 ? state.page - 1 : 1})),
  on(PagerActions.setPageSize, (state, action) => ({...state, pageSize: action.size}))
);

export function reducer(state: State | undefined, action: Action) {
  return pagerReducer(state, action);
}

无论我做什么

  on(PagerActions.toEnd, state => ({...state, page: Math.floor(rantSelectors.selectEntities.length / state.pageSize)})),

始终为 0。rantSelectors.selectCount.length 或以上。可能是因为长度为0。 我还需要知道 increment reducer 中“rant”实体的长度或数量。

我不知道如何获取实际值。

我在想...有一个实体计数选择器,并使用 props 在 toEnd 操作中传递该计数。另一种选择是副作用,但它们很令人困惑,而且恕我直言,这不是编写代码的正确方法(代码不可读,缺少直接原因/结果,是的,我知道,我不想争论它)。然后,即使产生副作用,如何在模块中定义它?这是 AppEffects 的副作用还是独特的副作用?我猜测是 AppEffects,因为它不在另一个模块中。

app.module.ts

    EffectsModule.forRoot([AppEffects]),

AppEffects = 几乎是空的,默认的 ng add 内容。

所以,是的,我需要获取 reducer 中 @ngrx/data 实体的状态,获取其实际值,或更优雅的方法。

最佳答案

我更喜欢保持组件清洁...我看到有两种解决方案可以解决您的问题

  1. 您可以通过向您的状态添加一个数字值,将 rantSelectors.selectEntities.length 的长度存储在存储的这一部分中。当您加载/更新 rantSelectors.selectEntities 时,您还会更新该存储区。
export interface State {
  page: number;
  pageSize: number;
  rantEntitiesSize: number;

// ...
   on(rantActions.loadSuccess, 
      rantActions.UpdateSuccess, //could include adding objects to the current loaded list
      rantActions.RemoveSuccess, //(negative number)
      (state, action) => 
        ({...state, rantEntitiesSize: (state.rantEntitiesSize + action)}),

}
  • 您可以保留toEnd操作而不是在reducer中使用它,而是构建一个在toEnd操作上调用的效果,该效果从另一个操作获取您需要的值存储的一部分,然后调用第二个操作将值传递给 reducer 。
  •   toEndPager$ = createEffect(() =>
        this.actions$.pipe(
          ofType(PagerActions.toEnd),
          withLatestFrom(this.store.select(rantSelectors.selectEntities.length)),
          switchMap(([{},length]) => {
            return of(PagerActions.toEndSuccess({ length });         
          })
        )
      ); 
    

    关于angular - ngrx 8 : Access state of @ngrx/data entity from reducer function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59776226/

    相关文章:

    html - 我们怎样才能使固定左侧导航栏旁边的容器响应?

    angular - 如何创建可配置服务 Angular 4

    angular - 如何将 Angular2 路由器连接到 ngrx/store?

    angular - @ngrx/store 从 v10 更新到 v11/v12

    html - 滚动时 Mat-Table 重叠菜单位于上方

    html - 使 flex 容器受窗口高度限制

    javascript - 如何在 Angular 4 中设置表单值?

    angular - 通过组件输出触发 ngrx 存储之外的副作用

    angular - 在特征内选择数据的 ngrx/entity 问题

    angular - 有没有使用 NGRX 和 angular-fire 的一个很好的例子