Доступ к другим частям состояния в Redux reducer
Я использую Redux и хотел бы установить флаг в состоянии, если пользователь изменил данные.
сначала я увлажняю свой магазин некоторыми данными с сервера:
let serverData = {toggle: true}
const store = configureStore({data: serverData, originalData: serverData})
у меня тогда есть несколько редукторов:
function data(state = {}, action) {
switch (action.type) {
case TOGGLE:
return {
...state,
toggle: !state.toggle
}
default:
return state
}
}
function changed(state = false, action) {
// This doesn't work; we are actually comparing state.changed.originalData and state.changed.data
return isEqual(state.originalData, state.data)
}
const rootReducer = combineReducers({
data,
originalData: (state={}) => state,
changed
})
что я хотел бы сделать здесь, это установить changed
флаг true, если state.data
не равно state.originalData
. Однако, используя combineReducers, я не могу получить доступ к этим частям состояния внутри моего changed
редуктор.
что больше всего идиоматические способ сделать это?
1 ответов
Мишель права, чтобы расширить его в традиционных терминах потока, подумайте о редукторе как о магазине, вы просто назвали один из ваших магазинов "данными", а другой "измененным" - это не семантика и показывает, что вы, вероятно, смущены тем, как они используются.
код changed
редуктор должен либо вернуть немодифицированное состояние, либо, если было сделано действие, которое его интересует, вернуть далее государство. Это не для выяснения, изменился ли ваш магазин - вот что subscribe
для.
const unsubscribe = store.subscribe(() =>
console.log('store was changed:', store.getState())
)
когда вы называете combineReducers
он вызовет каждый редуктор один раз, с действием @@redux/INIT
-- но не беспокойтесь об этом, поскольку это внутреннее. Важно понимать,что под каждым ключом редуктора инициализируется состояние. В вашем случае вы инициализировали data
к пустому объекту,changed
false, а originalData
к пустому объекту.
следующий, когда вы позвонили createStore
вы сказали "обновить магазины" data " и "originalData" с это начальное состояние от сервера". Итак, теперь состояние хранилищ "data" и "serverData" равно {toggle: true}
.
в этот момент оба объекта одинаковы.
впоследствии, когда вы называете store.dispatch
все ваши редукторы будут вызваны, чтобы они могли иметь возможность изменять состояние (и возвращать новый объект) под каждым ключом редуктора. Каждый редуктор имеет доступ только к своему собственному состоянию. Поэтому в вашем changed
редуктор вы не можете проверить в целом объектное равенство всего вашего государства.
однако вы можете проверить равенство объектов в подписке (смешанный ES5/6 здесь для Chrome 47)
'use strict';
const serverData = {toggle: true};
const TOGGLE = 'TOGGLE';
function data(state, action) {
state = state || {};
switch (action.type) {
case TOGGLE:
return Object.assign({}, state, {
toggle: !state.toggle
})
default:
return state
}
}
function originalData(state) {
state = state || {};
return state;
}
const rootReducer = Redux.combineReducers({
data,
originalData
});
const store = Redux.createStore(rootReducer, {data: serverData, originalData: serverData });
const unsubscribe = store.subscribe(() =>
console.log('on change equal?', store.getState().data === store.getState().originalData)
)
console.log('on load equal?', store.getState().data === store.getState().originalData);
store.dispatch({ type: TOGGLE });
консоль.вывод журнала должен быть:
on load equal? true
on change equal? false