1

我正在尝试创建一个具有特征状态和组合减速器的库。

我的特征缩减器如下所示:

索引.ts

export const storageFeatureKey = 'storage';

export interface StorageState {
  [fromBookEntries.bookEntriesFeatureKey]: fromBookEntries.State
}

export function reducers(state: StorageState | undefined, action: Action) {
  return combineReducers({
    [fromBookEntries.bookEntriesFeatureKey]: fromBookEntries.reducer
  })(state, action);
}

bookEntriesFeatures 看起来像这样:

book-entry.reducer.ts

export const bookEntriesFeatureKey = 'book-entries';

export interface State extends EntityState<WarehouseBookEntry> {
  selectedEntryId: number;
}

export const adapter: EntityAdapter<WarehouseBookEntry> = createEntityAdapter<WarehouseBookEntry>({
  selectId: (entry) => entry.id
});

export const initialState: State = adapter.getInitialState({
  selectedEntryId: null
});

export const reducer = createReducer(
  initialState,
  on(...),
  on(...)
);

export const getSelectedEntryId = (state: State) => state.selectedEntryId;

const {
  selectIds,
  selectEntities,
  selectAll,
  selectTotal
} = adapter.getSelectors();

export const getBookEntriesIds = selectIds;
export const getBookEntriesEntities = selectEntities;
export const getAllBookEntries = selectAll;
export const getTotalBookEntries = selectTotal;

在我的功能模块中,我使用我的功能密钥和功能缩减器导入 StoreModule.forFeature()。

不,我正在尝试根据选定的 id 选择一个条目。因此,我触发了一个操作,成功地将所选条目的 id 添加到我的图书条目状态。

要选择所选条目,我的功能选择器中有以下选择器:

索引.ts

export const selectSelectedBookEntry = createSelector(
  fromBookEntries.getBookEntriesEntities, // fromBookEntries is in my bookEntriesFeature
  selectSelectedBookEntryId, // simply returns the selected id
  (entries, selectedId) => {
    //console.log(entries, selectedId)
    //console.log("fired");
    return entries && entries[selectedId];
  }
);

当通过另一个调度的动作加载条目时,选择器只被调用一次(在数据加载之前)。我发现当我在功能选择器中从 bookEntriesAdapter 创建选择器时,它可以工作。像这样:

索引.ts

export const selectStorageState = createFeatureSelector<StorageState>(
  storageFeatureKey
);

export const selectBookEntriesState = createSelector(
  selectStorageState,
  state => state[fromBookEntries.bookEntriesFeatureKey]
);

const {
  selectIds,
  selectEntities: selectBookEntriesEntities,
  selectAll,
  selectTotal
} = fromBookEntries.adapter.getSelectors(selectBookEntriesState);

export const selectAllBookEntries = createSelector(
  selectBookEntriesState,
  selectAll
)

export const selectSelectedBookEntry = createSelector(
  selectBookEntriesEntities,
  selectSelectedBookEntryId,
  (entries, selectedId) => {
    //console.log(entries, selectedId)
    //console.log("fired");
    return entries && entries[selectedId];
  }
);

但为什么?我有点迷失了,试图理解为什么这不起作用。

上面不起作用的示例来自官方的ngrx doc(https://ngrx.io/guide/entity/adapter)。工作的一个来自ngrx/platform示例代码(https://github.com/ngrx/platform/blob/master/projects/example-app/src/app/books/reducers/index.ts)。

我认为没有必要,但我没有扩展 root-app-store-state,因为我无权访问它,因为它是一个库(试图绕过域驱动设计,我创建了一个功能库来处理这类问题)。或者这可能是问题所在?

如果有人能再解释一下,我将不胜感激。

4

1 回答 1

2

在您的代码中,您错过createFeatureSelector了它的集成。

首先从全局状态中选择您的特征状态,然后选择您需要的数据,这一点很重要。

当你使用这样的选择器时

const {
  selectIds,
  selectEntities,
  selectAll,
  selectTotal
} = adapter.getSelectors();

export const getBookEntriesEntities = selectEntities;

他们对此一无所知StoreModule.forFeature(FEATURE_KEY),您有责任为他们缩小全球状态。

为此createFeatureSelector,它会从全局状态中选择您的功能。

因此,要使用getBookEntriesEntities您需要首先选择您的功能,然后将此数据传递到getBookEntriesEntities.

const selectMyFeature = createFeatureSelector(FEATURE_KEY);

const selectMyFeatureEntities = createSelector(
  selectMyFeature,
  getBookEntriesEntities,
);

现在当我们使用store.select(selectMyFeatureEntities)它时,它知道如何从特征中选择数据。

在您的情况下,正确的代码是


const {
  selectIds,
  selectEntities,
  selectAll,
  selectTotal
} = adapter.getSelectors();

// put here feature name from .forFeature
const selectMyFeature = createFeatureSelector(FEATURE_KEY);

export const selectMyFeatureBooks = createSelector(
  selectMyFeature,
  state => state[fromBookEntries.bookEntriesFeatureKey]
);

export const getSelectedEntryId = createSelector(
  selectMyFeatureBooks,
  (state: State) => state.selectedEntryId,
);

export const getBookEntriesIds = createSelector(
  selectMyFeatureBooks,
  selectIds,
);
export const getBookEntriesEntities = createSelector(
  selectMyFeatureBooks,
  selectEntities,
);
export const getAllBookEntries = createSelector(
  selectMyFeatureBooks,
  selectAll,
);
export const getTotalBookEntries = createSelector(
  selectMyFeatureBooks,
  selectTotal
);

现在selectSelectedBookEntry将按预期工作。

于 2020-05-20T15:57:00.347 回答