我有一个NGRX商店看起来像这样。
export interface INavigationSettings {
gridLayout: {
[Breakpoints.Small]: GridLayout;
[Breakpoints.Large]: GridLayout;
};
//...
}
我有一个动作,将应用修改这些GridLayout
const SET_NAVIGATION_GRID_VISIBILITY = (state: State, action: featureAction.SetNavigationGridVisibility) => {
state.navigation.gridLayout[action.payload.size].visibility = {
...state.navigation.gridLayout[action.payload.size].visibility,
...action.payload.visibility
};
return state;
};
问题是,我的选择器 selectNavigationGridLayout
export const selectSettingsState: MemoizedSelector<object, State> = createFeatureSelector<State>('settings');
export const gridLayout = (state: State): {
Small: featureModels.GridLayout;
Large: featureModels.GridLayout;
} => state.navigation.gridLayout;
export const selectNavigationGridLayout: MemoizedSelector<object, {
Small: featureModels.GridLayout;
Large: featureModels.GridLayout;
}> = createSelector(selectSettingsState, gridLayout);
从不捕捉任何变化,也不调用变化状态槽的应用程序.这是很好的工作之前,当我有一个单一的对象gridLayout,但因为我是做移动,我分开在2件=>。
gridLayout: {
[Breakpoints.Small]: GridLayout;
[Breakpoints.Large]: GridLayout;
};
现在它从来没有触发。
我也尝试过
return {
...state
}
EDIT :
我改成了这个
const SET_NAVIGATION_GRID_VISIBILITY = (state: State, action: featureAction.SetNavigationGridVisibility) => {
return {
...state,
navigation: {
...state.navigation,
gridLayout: {
...state.navigation.gridLayout,
[action.payload.size]: {
...state.navigation.gridLayout[action.payload.size],
visibility: {
...state.navigation.gridLayout[action.payload.size].visibility,
...action.payload.visibility
}
}
}
}
};
};
它的工作,但它是可怕的,是不是有一个更好的方法?
你最后的编辑工作是因为你返回的是新状态,而不是突变现有状态。
这里有一些 "更漂亮 "的解决方案来返回新状态。
另一种解决方案是使用 ActionReducerMap
来分解你的减速器,使其专注于某一块状态。
我看到你的顶层功能名为 settings
. 所以你的商店看起来有点像这样。
interface StoreState {
settings: SettingsFeatureState;
}
interface SettingsFeatureState {
navigation: INavigationSettings;
}
interface INavigationSettings {
gridLayout: GridLayoutState;
}
interface GridLayoutState {
[Breakpoints.Small]: GridLayout;
[Breakpoints.Large]: GridLayout;
}
而你的设置还原器看起来就像这两个中的一个:
function settingsReducer(state: SettingsFeatureState, action: Action): SettingsFeatureState {
// ...
}
// or
function navigationReducer(state: INavigationSettings, action: Action): INavigationSettings {
// ...
}
const settingsReducer: ActionReducerMap<SettingsFeatureState> = {
navigation: navigationReducer
};
做以下步骤来分解你的状态还原器,甚至更多。
创建一个网格布局reducer,像这样。
function gridLayoutReducer(state: GridLayoutState, action: Action): GridLayoutState {
// ...
}
const SET_NAVIGATION_GRID_VISIBILITY = (state: GridLayoutState, action: featureAction.SetNavigationGridVisibility): GridLayoutState => {
return {
...state,
[action.payload.size]: {
...state[action.payload.size],
visibility: {
...state[action.payload.size].visibility,
...action.payload.visibility
}
}
};
};
然后,修改你的navigationReducer,将其注册为 gridLayoutReducer
如下图所示。
const navigationReducerMap: ActionReducerMap<INavigationSettings> = {
gridLayout: gridLayoutReducer
}
// This function has the following signature:
// navigationReducer(state: INavigationSettings, action: Action): INavigationSettings
const navigationReducer = combineReducers(navigationReducerMap)
如果你真的不想返回新的状态,你可以保留原来的逻辑,但稍作修改,使用类似于 lodash
来深度克隆状态。
const SET_NAVIGATION_GRID_VISIBILITY = (state: State, action: featureAction.SetNavigationGridVisibility) => {
const newState = _.deepClone(state)
newState.navigation.gridLayout[action.payload.size].visibility = {
...newState.navigation.gridLayout[action.payload.size].visibility,
...action.payload.visibility
};
return newState;
};
这将返回新的状态,因为你已经完全克隆了状态。但是,这种方法会使用更多的资源,因为你克隆整个状态只是为了修改几个属性。