- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个应用程序,它有多个具有相同 reducer 功能的商店。我尝试制作一个通用 reducer ,它运行良好。
通用 reducer 设置:
interface State<T> {
itemList : T[]
}
const initialState: State<any> = {
itemList: []
}
const createReducer = <T>(type: string) => {
return <T>(state = initialState, action: any): State<T> => {
switch (action.type) {
case types.get(type).Add:
return {
...state,
itemList: [...state.itemList, action.payload]
}
case types.get(type).AddList:
return {
...state,
itemList: [...state.itemList, ...action.payload]
};
default:
return state;
}
}
}
然后我会按如下方式组合 reducer :
export const reducers: ActionReducerMap<AppState> = {
vehiculeState: createReducer<Vehicule>('vehicule'),
rentState: createReducer<Rent>('rent'),
clientState : createReducer<Client>('client'),
companionState : createReducer<Client>('companion'),
paymentState : createReducer<Payment>('payment'),
notificationState : createReducer<Notification>('notification'),
employeeState : createReducer<Employee>('employee')
}
问题是,通过切换到通用模式,我将不得不重写我的应用程序的大部分内容,因为我已经创建了多个 reducer,其状态包含名为 (clientList
, vehiculeList
,...),属性名称 itemList
信息量不大。所以我的问题是如何切换到通用模式并保持状态属性不变?
当前 reducer 的示例:
export function rentReducer(state = initialState, action: rentActions.RentActions): State {
switch(action.type){
case rentActions.ADD_RENT:
return{
...state,
rentList : [...state.rentList, action.payload]
}
case rentActions.ADD_RENT_LIST:
return {
...state,
rentList : [...state.rentList, ...action.payload]
};
default:
return state;
}
}
最佳答案
您可以使用字符串来表示 itemList
属性名称,并使用映射类型将该字符串转换为 State
类型的类型安全属性。一个缺点是映射类型不支持使用扩展运算符,但我们可以使用 Object.assign
// We add an extra parameter to State that will be the property name passed in as a string literal type
// So State<Vehicle, 'vehicleList'> will be a type equivalent to { vehicleList : Vehicle[] }
type State<T, TListName extends string> = {
[P in TListName] : T[]
}
// We create a function that creates the initial state by initializing an object with an empty array and the given property name
const initialState = <T, TListName extends string>(itemListName: TListName): State<T, TListName> => {
let result = {} as State<any, TListName>;
result[itemListName] = [];
return result;
};
// Since we can't use the spread operator, we create a new function that updates the state
// state will be the original state,
// itemListName the property name which contains the list
// newItems will be the new list
const updateState = <T, TListName extends string>(args: { state: State<T, TListName>, itemListName: TListName, newItems: T[] }): State<T, TListName> => {
return Object.assign({},args.state, {
[args.itemListName] : args.newItems
});
}
// We will use a 2 function approach for the createReducer function
// We do this in order to be able to specify the item type (T) explicitly,
// but not have to specify the string literal type TListName and let it be inferred
const createReducer = <T>(type: string) => <TListName extends string>(itemListName: TListName) => {
return (state = initialState<T, TListName>(itemListName), action: any): State<T, TListName> => {
switch (action.type) {
case types.get(type).Add:
return updateState({
state,
itemListName,
newItems: [...state[itemListName], <T>action.payload]
});
case types.get(type).AddList:
return updateState({
state,
itemListName,
newItems: [...state[itemListName], ...<T[]>action.payload]
})
default:
return state;
}
}
}
export const reducers = {
vehiculeState: createReducer<Vehicule>('vehicule')('vehiculeItems'),
rentState: createReducer<Rent>('rent')('rentItems'),
clientState : createReducer<Client>('client')('clientItems'),
companionState : createReducer<Client>('companion')('companionItems'),
paymentState : createReducer<Payment>('payment')('paymentItems'),
notificationState : createReducer<Notification>('notification')('notificationItems'),
employeeState : createReducer<Employee>('employee')('employeeItems'),
}
关于angular - ngrx:通用 reducer ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50130037/
我已经建立了这个IStore: export interface IStore { user: IUser; sources: ISourceRedux; } 其中IUser是: export
store.select()发出先前的存储状态。 是否可以订阅从“此刻开始”的更改,而无需获取先前的商店值(value)? 最佳答案 如果您对第一个发出的值不感兴趣,则应该可以使用 skip 运算符:
我已将我的 ngrx 代码更新到版本 8(使用 Action Creator 等),但我现在不知道如何在 NgRx Store DevTools 中使用 Dispatcher。 在我能够发送这样的操作
我正在开发一个新的 angular 4 plus @ngrx 4 项目。 我希望对加载的数据具有搜索功能。 例如,所有联系人信息都已加载到组件中。 联系人列表将过滤与搜索文本匹配的联系人姓名。 Ple
我正在使用 Ngrx 和 Angular2 构建一个移动应用程序。当用户从我的应用程序中注销时,我想清除商店?谁能知道该怎么做? 最佳答案 您应该在每个 reducer 中有一个明确的操作,这将清理商
我看到很多代码示例,其中 store.dispatch() 调用直接发生在 Angular 组件中。让一个愚蠢的 Angular 组件访问整个 Store 不是很糟糕吗?为什么不将所有的 Action
ngrx 的支持者声称 (here for example),您可以并且应该将所有应用程序状态保存在单个 Store 中。这表明 @ngrx/Store 可以用于缓存,因为缓存的内容是一种应用程序状态
我的应用程序在调度某个 Action 时没有调度某些 Action 或某些效果没有被调用,这有问题(请参阅 ngrx effect not being called when action is di
下面的代码片段有什么作用?取自此 file . export const getCollectionLoading = createSelector(getCollectionState, fromC
如果在同一个商店上分派(dispatch)多个操作: store.dispatch(new SomeAction()); store.dispatch(new SomeOtherAction());
我试图了解 typeof 效果在 ngrx 中是如何工作的,如果我在我的应用程序模块中声明: .... @NgModule({ imports: [ EffectsModule
任何人都可以建议在角度应用程序中使用 ngrx 进行状态管理时如何控制台记录状态。我已经浏览了 ngrx-store-logger,但是文档并不清楚如何创建元 reducer 和使用这个库。 最佳答案
我一直在阅读ngrx示例应用程序的代码并找到两个函数调用 createFeatureSelector('auth'); 和 createSelector(selectAuthState,(state:
我正在使用 Angular 8 和 NGRX 8。我有一个操作: export const loadEnvironment = createAction( LicencingActionTypes
我正在使用 Angular 8 和 NGRX 8。我有一个操作: export const loadEnvironment = createAction( LicencingActionTypes
以下示例取自 @ngrx example . 我以这种方式理解这个 observable。第一map函数获取 payload这是要添加的书,再次由mergeMap处理它保存到数据库的位置。 原码:
我目前正在使用 NgRx Data 对我项目中的几个实体执行 CRUD 操作。现在,我必须开发分页。因此,REST API 响应将如下所示: { "page": 1, "per_pag
如何在 NGRX 中访问(读取)另一个 reducer 中的 reducer 状态?这是一个与 this 非常相似的问题.NGRX 是否为此提供任何其他解决方案? 最佳答案 我在考虑做类似的事情时偶然
我正在尝试按属性过滤掉有效负载数据。 //reducer.ts case MessagesActionTypes.LOAD_Message_SUCCESS: { console.lo
我有效果类,我想根据路由器参数 ID 加载详细信息 @Effect() getDetails$ = this.actions$.ofType(DetailActions.GET_DETAILS).
我是一名优秀的程序员,十分优秀!