【问题标题】:Extracting specific data from ngrx/store从ngrx/store中提取特定数据
【发布时间】:2017-06-13 10:07:06
【问题描述】:

所以我已经多次阅读this 的帖子,但现在定义的设置和示例与store example app 中显示的方法不同。

我已经编写了我的商店代码,很大程度上基于示例应用程序,所以如果我们继续使用示例应用程序作为本文中的参考:

图书缩减器:

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;

reducers index.ts(缩短但保留相关信息):

import { createSelector } from 'reselect';
import { compose } from '@ngrx/core/compose';
import { storeFreeze } from 'ngrx-store-freeze';
import { combineReducers } from '@ngrx/store';
import * as fromBooks from './books';


export interface State {
  books: fromBooks.State;
}

const reducers = {
  books: fromBooks.reducer,
};

const productionReducer: ActionReducer<State> = combineReducers(reducers);
export function reducer(state: any, action: any) {
    return productionReducer(state, action);

}

export const getBooksState = (state: State) => state.books;
export const getBookEntities = createSelector(getBooksState, fromBooks.getEntities);
export const getBookIds = createSelector(getBooksState, fromBooks.getIds);

现在我不太明白“查询”是如何构建的,我想要做的就是将一个 ID 说“456”传递给一个函数,该函数将使用 id 从书中查看 State 456"。将此数据返回到 Book 的 observable 中,以便我可以在模板/组件中使用它。

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

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

【问题讨论】:

    标签: angular rxjs ngrx


    【解决方案1】:

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

    首先您需要将选定的 ID 存储在您的商店中,在这种情况下,您需要将“selectedBookId”属性作为新的操作,如 SELECTED_BOOK

    第二要获取所选书籍,您需要创建一个选择器,将 selectedBookId 与您的实体数组结合起来,例如:

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

    index.ts

    export const getSelectedBook = createSelector(getBookState, fromBook.getSelected);
    

    最后获取您需要调用选择器的图书对象

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

    【讨论】:

    • 啊,我明白了,我没有意识到我需要先将要检索的书存储在商店中,这确实使示例代码有意义,感谢您的解释。
    • 所以让我们在我的组件中说,我想通过可观察的方式观看两本不同的书,我该怎么做?我希望 getSelected 可以获取书籍 ID,然后我可以使用 fromRoot.getSelectedBook(BookID),但是使用这种方法我仅限于一本书?
    • 如果你在 state 中添加一个数组,比如 selectedBookId[]。
    • 然后在组件中做什么 getSelectedBook[id] 将所需的书 ID 映射到 observable 中?
    • 如果我调用诸如“this.book$ = this.store.select(fromRoot.getSelectedBook);”之类的选择器然后用const bookExtensiond$ = book$ // Only fire subscription when object has someValue .filter(x =&gt; !!x.someValue) .subscription(...) 之类的东西扩展它,但是当状态被重置时,这些可观察对象会因Cannot read property 'someValue' of undefined 之类的错误而被破坏。有什么想法吗?
    猜你喜欢
    • 2017-08-10
    • 2022-04-29
    • 2018-03-30
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    • 2016-05-30
    • 2013-10-24
    相关资源
    最近更新 更多