gpt4 book ai didi

angular - ngrx:通用 reducer

转载 作者:搜寻专家 更新时间:2023-10-30 21:19:20 24 4
gpt4 key购买 nike

我有一个应用程序,它有多个具有相同 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com