Angular 从ngrx/存储中提取特定数据

Angular 从ngrx/存储中提取特定数据,angular,rxjs,ngrx,Angular,Rxjs,Ngrx,所以我已经读了几遍这篇文章,但是定义的设置和示例现在与中显示的方法有所不同 我已经编写了基于示例应用的商店代码,因此如果我们在本文中继续使用示例应用作为参考: 书籍减速机: export interface State { ids: string[]; entities: { [id: string]: Book }; selectedBookId: string | null; }; const initialState: State = { ids: [], entit

所以我已经读了几遍这篇文章,但是定义的设置和示例现在与中显示的方法有所不同

我已经编写了基于示例应用的商店代码,因此如果我们在本文中继续使用示例应用作为参考:

书籍减速机:

export interface State {
  ids: string[];
  entities: { [id: string]: Book };
  selectedBookId: string | null;
};

const initialState: State = {
  ids: [],
  entities: {},
  selectedBookId: null,
};

export function reducer(state = initialState, action: book.Actions | collection.Actions): State {
  switch (action.type) {
    case book.ActionTypes.SEARCH_COMPLETE:
    case collection.ActionTypes.LOAD_SUCCESS: {
      const books = action.payload;
      const newBooks = books.filter(book => !state.entities[book.id]);

      const newBookIds = newBooks.map(book => book.id);
      const newBookEntities = newBooks.reduce((entities: { [id: string]: Book }, book: Book) => {
        return Object.assign(entities, {
          [book.id]: book
        });
      }, {});

      return {
        ids: [ ...state.ids, ...newBookIds ],
        entities: Object.assign({}, state.entities, newBookEntities),
        selectedBookId: state.selectedBookId
      };
    }

export const getEntities = (state: State) => state.entities;
export const getIds = (state: State) => state.ids;
减速器索引.ts(缩短但保留相关信息):

从“重新选择”导入{createSelector};
从'@ngrx/core/compose'导入{compose};
从“ngrx存储冻结”导入{storeFreeze};
从'@ngrx/store'导入{combinereducer};
从“/books”导入*作为fromBooks;
导出接口状态{
书籍:fromBooks.State;
}
常数减缩器={
书籍:fromBooks.reducer,
};
const productionReducer:ActionReducer=组合减速机(减速机);
导出函数减速器(状态:任意,操作:任意){
返回productionReducer(状态、动作);
}
export const getbookstate=(state:state)=>state.books;
export const getBookEntities=createSelector(GetBookState,fromBooks.getEntities);
export const getBookIds=createSelector(getbookstate,fromBooks.getid);
现在我不能完全理解的是“查询”是如何构建的,我想能够做的是将一个ID(比如“456”)传递给一个函数,该函数将从ID为“456”的书中查看内部状态。将这些数据返回到一本可观察的书中,这样我就可以在我的模板/组件中使用它

我已经看了几个小时的示例代码,当我认为我已经掌握了它的时候,我无法找出我做错了什么。如果有人能够解释如何构建接受自定义参数的选择器


我使用了示例应用程序中的确切代码,希望如果找到答案,将对未来的读者有所帮助。

当您使用redux模式时,您必须通过操作完成所有操作

首先您需要将所选ID存储在您的存储中,在这种情况下,“selectedBookId”属性是一个新操作,类似于selected\u BOOK

Second要获取所选图书,您需要创建一个选择器,将所选图书ID与实体数组相结合,如:

export const getSelected = createSelector(
  getEntities,
  getSelectedId,
  (entities , selectedId) => entities.find(entities => entities.id === selectedId)
);
索引

export const getSelectedBook = createSelector(getBookState, fromBook.getSelected);
最后要获取图书对象,需要调用选择器

this.book$ = this.store.select(fromRoot.getSelectedBook);

啊,我明白了,我没有意识到我需要先将我想要检索的书存储在商店里,这确实让示例代码变得有意义,感谢您的解释。所以让我们在我的组件中说,我想通过一个可观察的工具观看两本不同的书,我该怎么做?我希望getSelected可以获取一个book ID,然后我可以从root.getSelectedBook(BookID)执行此操作,但使用此方法,我仅限于一本书?如果向selectedBookId[]这样的状态添加一个数组,那么在组件中getSelectedBook[ID]会如何将所需的book ID映射到可观察对象中?如果我调用一个选择器,例如“this.book$=this.store.select(fromRoot.getSelectedBook);“然后使用类似于
const bookExtensiond$=book$//的内容来扩展它,仅当对象具有someValue.filter(x=>!!x.someValue.subscription(…)时才触发订阅。”
然而,当状态被重置时,这些观察值会被一个错误打破,例如
无法读取未定义的属性“someValue”
。有什么想法吗?
this.book$ = this.store.select(fromRoot.getSelectedBook);