angular - 从 ngrx/store 获取单个项目

标签 angular typescript redux store ngrx

我编写了以下缩减器来将状态项存储在我的 Angular 2 应用程序中。这些项目是金融工具(例如股票/货币)的报价。

我的 Reducer 实现如下:

export const offersStore = (state = new Array<Offer>(), action:Action) => {
switch(action.type){

    case "Insert":
        return [
            ...state, action.payload
        ];
    case "Update":
            return state.map(offer => {
                    if(offer.Instrument === action.payload.Instrument)
                    {
                        return Object.assign({}, action.payload);
                    }
                    else return offer;
            });
    case "Delete":
        return state.filter(offer => offer.Instrument !== action.payload )
    default:
        return state;
    }

我设法让插入、更新和删除正常工作——尽管这并不容易。我发现 Redux 是一种范式转变,与我多年来的编码方式不同。

我的应用程序上有一个仪器组件/页面 - 它显示了一个特定仪器的所有可用信息,由 InstrumentId 指示,例如“EUR/USD”(存储在 payload.Instrument 属性中)。

我的问题是,我不确定如何有效地搜索特定乐器并将其从商店中取出。不仅如此,我还希望在商店中的乐器更新时更新我获取的乐器,因为它们经常通过服务器的 websocket 推送进行更新。所以我真的需要在商店中搜索特定的仪器,并将其作为 Observable 返回,这将根据推送到商店的新数据继续更新 View 组件。

我怎样才能做到这一点?

最佳答案

对于在 reducer 上调用的每个操作,都会返回新状态。

从问题中的示例代码来看,状态只是一个工具列表。
没有索引,所以检查仪器是否在列表中的唯一方法是搜索整个列表。

但是如果你的状态是一本字典呢?此外,如果您将索引列表与字典分开会怎么样?

你的状态类型是这样的:

export interface OfferState {
  ids: string[];
  entities: { [id: string]: IOffer };
};

任何时候执行一个 Action ,都会返回新的状态。这是 Redux 中的一个重要概念,因为状态永远不能直接改变。当你编写你的 reducer 时,你实际上最好严格执行这一点:(假设你有你“提供 reducer ”和另一个 reducer ,你将它们组合成一个组合:

> export default compose(storeFreeze, combineReducers) ({   oether:
> otherReducer,   offers: offersReducer });

在 Redux 中很容易出错——但是如果你试图直接改变状态,使用 storeFreeze 会抛出一个错误。关键是 Action 会改变状态,并产生新的状态。它们不会更改现有状态 - 它让我们可以撤消/重做...等。

使用上面的示例,我会将其用作我的 Offer 的 reducer:

export interface OfferState {
  ids: string[];
  entities: { [id: string]: IOffer };
};

export default function(state = initialState, action: Action): OfferState {
    switch(action.type){
        case OfferActions.INSERT:
        const offer : IOffer = action.payload;
        return {
            ids: [ ...state.ids, action.payload.Instrument ],
            entities: Object.assign({}, state.entities, { [action.payload.Instrument]: action.payload})
        };
        case OfferActions.UPDATE:
            return {
                ids: [...state.ids],
                entities: Object.assign({}, state.entities,  { [action.payload.Instrument]: action.payload})
            }

        default:
            return state;
    }
}

请注意,通过 object.assign(深拷贝)对临时状态进行更改,然后返回新状态。

这个问题的另一个答案有点令人困惑。它详细介绍了如何组合不同的 reducer ,但对我来说意义不大。

在你的 reducers/index.ts 中你应该有一个类型:

export interface AppState {
  otherReducer: OtherReducer;
  offers: fromOffersReducer.OfferState;
}

在这个 index.ts 中,你应该有获取 reducers 的函数:

export function getOfferState() {
  return (state$: Observable<AppState>) => state$
    .select(s => s.offers);
}

export function getOtherReducer() {
  return (state$ : Observable<AppState>) => state$
    .select(s => s.otherReducer)
}

在我们的 offerReducer 和我们的 otherReducer 中,我们定义了可以查询我们需要的数据的函数。这些是匿名函数,目前没有链接到任何东西,但我们稍后会链接它们(到 getReducerFunctions)。

这些函数的例子:

export function getOfferEntities() {
  return (state$: Observable<OfferState>) => state$
    .select(s => s.entities);
};

export function getOffer(id: string) {
  return (state$: Observable<OfferState>) => state$
    .select(s => s.entities[id]);
}

这什么都不做。除非我们将它应用到一些我们简化的有用数据(例如 offersRedeucer),然后我们像这样将两者结合起来:

import offersReducer, * as fromOffersReducer from './OffersReducer';

 export function getOfferEntities() {
   return compose(fromOffersReducer.getOfferEntities(), getOfferState());
 }

  export function getOffer(instrument:string) {
   return compose(fromOffersReducer.getOffer(instrument), getOfferState());
 }

关于angular - 从 ngrx/store 获取单个项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38957510/

相关文章:

reactjs - 调度不改变 redux 状态

angular - 循环到 Typescript 中的对象

typescript - 类型 'IterableIterator<[number, any]>' 不是数组类型或字符串类型

react-native - I18Next - 等待使用本地数据设置 Redux 存储

Angular2 - 没有自定义功能的 ngFor trackby 索引

javascript - 将 id 属性添加到 FormControl 元素或父 Angular 7

javascript - 当条件为真时从 Redux 商店取消订阅?

angular - 在 Angular 中动态配置 Firebase 环境

Angular 日历 subFn 不是函数

angular-cli 服务器 - 如何指定默认端口