从ngrx/store获取单个项目 [英] get single item from ngrx/store

查看:55
本文介绍了从ngrx/store获取单个项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've written the following reducer to store the state items in my Angular 2 app. The Items are price offers for Financial Instruments (e.g. stocks/currencies).

我的Reducer实现如下:

My Reducer Implementation is as follows:

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与过去多年的编码方式发生了范式转换.

I managed to get Inserts, Updates and Deletes working - although it wasn't easy. I find Redux to be something of a paradigm shift away from how I've been coding for years.

我的应用程序上有一个乐器组件/页面-该页面显示了一个特定乐器的所有可用信息,如InstrumentId所示. "EUR/USD"(存储在payload.Instrument属性中).

I've got an Instrument Component/Page on my App - which shows all available information for one specific Instrument, indicated by InstrumentId e.g. "EUR/USD" (stored in the payload.Instrument property).

我的问题是,我不确定如何有效地搜索特定乐器并将其从商店中取出.不仅如此,而且我还希望如果商店中的仪器经常通过服务器上的Websocket推送进行更新,则我获取的仪器也会进行更新.因此,我确实需要在商店中搜索特定的仪器,并将其作为Observable返回,这将继续根据推送到商店的新数据来更新View Component.

My problem is, I'm not sure how to efficiently search for a specific instrument and grab it out of the store. Not only this, but I also want the instrument I fetch to be updated if the Instrument in the store is updated as they are frequently via websocket push from the server. So I really need to search the store for a specific instrument, and return it as an Observable, that will continue to update the View Component based on new data that gets pushed to the store.

我该如何实现?

推荐答案

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

For every action that is called on a reducer, the new state is returned.

从问题中的示例代码中,状态只是工具列表.
没有索引,因此检查工具是否在列表中的唯一方法是搜索整个列表.

From the example code in the question, state is just a list of instruments.
There's no index, so the only way to check if an instrument is in the list is to search the whole list.

但是,如果您的州是一本字典该怎么办?此外,如果您将索引列表与字典分开保存怎么办?

But what if your state was a dictionary? Furthermore, what if you kept a list of indexes seperate to the dictionary?

您的州类型是:

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

每次执行动作时,都会返回新状态.在Redux中,这是一个重要的概念,因为状态永远不能直接突变.实际上,在编写化简器时最好严格执行此操作:(例如,您已经提供了化简器"和另一个化简器",则将它们与compose组合为一个:

Any time an action is executed, the new state is returned. It is an important concept in Redux, because state can never be mutated directly. You're actually best strictly enforcing this when you compose your reducer: (say you've got you "offers reducer" and another reducer, you combine them to one with compose:

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

在Redux中做错事情很容易-但是,如果您尝试直接更改状态,则使用storeFreeze会引发错误.关键是动作会改变状态,并建立新的状态.他们不更改现有状态-允许我们撤消/重做...等等.

Its easy to do things wrong in Redux - but using storeFreeze will throw up an error if you try to mutate the state directly. The point is that actions change state, and make a new state. They don't change the existing state - it lets us undo/redo... etc.

使用上面的示例,我将其用作我的优惠的简化器:

Using your example above I would use this as my Offer's 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(深拷贝)对临时状态进行了更改,然后返回了新状态.

note that changes are made to a temporary state via object.assign (deep copy) and then the new state is returned.

该问题的另一个答案有点令人困惑.它详细介绍了如何组合不同的异径管,但对我而言并没有多大意义.

The other answer to the question was a bit confusing. It went into the detail of how to combine different reducers, but it didn't make much sense to me.

在reducers/index.ts中,您应该输入以下类型:

in your reducers/index.ts you should have a type:

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

在此index.ts内,您应该具有获取减速器的功能:

inside this index.ts, you should have functions that get the 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).

inside our offerReducer and our otherReducer, we define functions that can query the data we need. These are anonymous functions, that are not linked to anything at present, but we will link them later (to the 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),然后像这样将两者结合在一起:

this does nothing. unless we apply it to some useful data (e.g. the offersRedeucer) that we made ealier, and we combine the two like this:

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());
 }

这篇关于从ngrx/store获取单个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆