我正在玩Redux并构建由一些示例数据驱动的应用程序。在我的应用程序中,我有一个名为" birdInfo"其中有一些状态存储在Redux商店中。
我已经编写了一个reducer来更新商店的面板状态(如果是打开或关闭)但是由于这个属性是嵌套对象,我不得不做一些Object.assign调用来更新减速器中的状态。
我设法让状态更新,但底层对象被Object.assign调用覆盖:
查看下面的代码我可能会过滤掉旧的panelOpen状态并在第3级合并中传递该状态的其他部分,但这看起来有点笨拙。我也可以使用let newObj = JSON.parse(JSON.stringify(oldObj));
进行深度合并,但这看起来并不理想。
const toggleBirdInfo = (state, action) => {
const newPanelState = {}
const newBirdInfoState = {}
const newState = {}
// Update 3rd level of state object
if (state.birdInfo[action.id].panelOpen === false) {
Object.assign(newPanelState, state.birdInfo[action.id], {panelOpen: true})
} else {
Object.assign(newPanelState, state.birdInfo[action.id], {panelOpen: false})
}
// Update 2nd level of state object
Object.assign(newBirdInfoState, state.birdInfo, {[action.id]: newPanelState})
//Update 1st level of state object
Object.assign(newState, state, {birdInfo: newBirdInfoState})
return newState
}
const rootReducer = (state = DEFAULT_STATE, action) => {
switch (action.type) {
case BIRD_INFO_TOGGLE:
return toggleBirdInfo(state, action)
case UPDATE_SEARCH:
return updateSearch(state, action)
default:
return state
}
}
进行这种深度合并的最佳方法是什么?
答案 0 :(得分:0)
我认为你的birdInfo减速器应该是这样的:
const toggleBird = (state, action) => {
return { ...state, birdInfo[action.id].panelOpen: !birdInfo[action.id].panelOpen }
}
export default function (state = {}, action) {
switch(action.type) {
case 'TOGGLE_BIRD':
return toggleBird(state, action);
default:
return state;
}
}
Redux处理整个状态的更新,您只需要关注状态的这一小部分。使用ES6扩展语法(...
中的{ ..state, }
),您只需更新您指定的密钥。
请参阅Redux文档中的Using Object Spread Operator以及整个Redux文档。
编辑:如果没有展开运算符,您的toggleBird
函数将类似于:
const toggleBird = (state, action) => {
return Object.assign({}, state, {
birdInfo[action.id].panelOpen: !birdInfo[action.id].panelOpen
})
}
答案 1 :(得分:-1)
var data = { a: { b: { c: [ 3, 4, 5 ] } } };
const { immutable } = require('immutable')
var nested = immutable(data);
nested.update('a', () => {
return immutable.fromJS('a')
});
Result
nested.toJSON() = { a : a };