Ваше последнее редактирование работает, потому что вы возвращаете новое состояние, а не изменяете существующее состояние.
Вот несколько «более симпатичных» решений для возврата нового состояния.
Решение 1: ActionReducerMap
Другое решение - использовать 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
};
Выполните следующие шаги, чтобы еще больше разложить ваши редукторы состояния.
Создайте редуктор макета сетки следующим образом:
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
}
}
};
};
Затем измените ваш Navigation-Reducer, зарегистрируйте gridLayoutReducer
следующим образом:
const navigationReducerMap: ActionReducerMap<INavigationSettings> = {
gridLayout: gridLayoutReducer
}
// This function has the following signature:
// navigationReducer(state: INavigationSettings, action: Action): INavigationSettings
const navigationReducer = combineReducers(navigationReducerMap)
Решение 2: Состояние клонирования
Если вы действительно не хотите возвращать новое состояние, вы можете сохранить исходный лог c с небольшим изменением, используя что-то вроде 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;
};
Возвращает новое состояние, так как вы полностью клонировали это состояние. Однако при таком подходе будет использоваться гораздо больше ресурсов, поскольку вы клонируете все состояние просто для изменения нескольких свойств.