redux NgRx视图模型混淆

fcg9iug3  于 2023-02-04  发布在  其他
关注(0)|答案(2)|浏览(134)

抱歉,如果这没有意义,也许我错过了一些基本的东西,但我有以下困境:
1.我正在从后端接收项目列表,类似于:

interface Item {
  id: number;
  userId: number;
  categoryId: number;
}

1.我还获得了用户和类别的列表,并将它们保存在我的商店中:

interface User {
  id: number;
  name: string;
}

interface Category {
  id: number;
  name: string;
}

1.我想使用这三个类来派生ItemVM视图模型,它将存储派生的数据:

interface ItemVM {
  id: number;
  userName: string;
  categoryName: string;
}

我的理解是我应该创建一个选择器,如下所示:

// map userId and categoryId to user.name and category.name
export const selectItemViewModel = createSelector(

  // get users, categories, and items
  selectUsers,
  selectCategories,
  selectItems,

  // map them
  (users, categories, items) => {
    return items.map(i => <ItemVM>{
      id: i.id,
      userName: users.find(u => u.id === i.userId).name,
      categoryName: categories.find(c => c.id === i.categoryId).name,
    });
  }

);

但是我不明白的是,既然这个选择器不是一个可观察的,我如何确保在调用它时用户、类别和项目已经被加载?

3df52oht

3df52oht1#

选择器是单个真值状态源的纯函数(带有一些记忆功能),可以通过浏览器扩展Redux DevTools查看。
如果您关心loaded,请将其添加到每个实体的状态中。
以下使用最新版本15.2.1@ngrx/entity

项目实体状态示例,每个实体重复

行动

export const apiActions = createActionGroup({
  source: 'Item/API',
  events: {
    'Load Items': emptyProps(),
    'Load Items Success': props<{ items: Item[] }>(),
    'Load Items Failure': props<{ error: string }>()
  },
});

还原剂

export interface ItemsState extends EntityState<Item> {
  loaded: boolean;
}

export const adapter: EntityAdapter<Item> = createEntityAdapter<Item>();

const initialState: ItemsState = adapter.getInitialState({
  // set initial required properties
  loaded: false
});

const reducer = createReducer(
  initialState,
  ...
  on(apiActions.loadItemsSuccess, (state, { items }) =>
    adapter.setAll(items, { ...state, loaded: true })
  ),
  ...
);

export const itemsFeature = createFeature({
  name: 'items',
  reducer
});

// register via StoreModule.forFeature(itemsFeature)

选择器

export const {
  // selector for each feature state property
  selectEntities,
  selectLoaded
} = itemsFeature;

然后组成多要素选择器

import { selectLoaded as selectItemsLoaded } from '<path>/items.selectors.ts';
import { selectLoaded as selectUsersLoaded } from '<path>/users.selectors.ts';
import { selectLoaded as selectItemsLoaded } from '<path>/categories.selectors.ts';

export const selectItemVmLoaded = createSelector(
  selectItemsLoaded,
  selectUsersLoaded,
  selectItemsLoaded,
  (l1, l2, l3) => ({ l1 && l2 && l3 })
)

可以将selectItemVmLoaded添加到选择器中,作为了解是否只返回[]并等待API调用的简单方法。
您可以在服务中显示为,例如,用于显示微调器/ backbone 组件

itemVmLoaded$ = this.store.select(selectItemVmLoaded);
cgyqldqp

cgyqldqp2#

这是一个使用distinctUntilChange()的选择器,它将在 Bootstrap 中由每个reducer的初始状态初始化,因此使用空数组而不是null进行初始化;)
所以你所做是正确的,这里一切都很好。

相关问题