Javascript 在Redux reducer中何时以及哪些状态部分应该被深度克隆?
很长一段时间以来,我一直在这样写我的简化:Javascript 在Redux reducer中何时以及哪些状态部分应该被深度克隆?,javascript,reactjs,redux,Javascript,Reactjs,Redux,很长一段时间以来,我一直在这样写我的简化: const init = { a: 'b' } const reducerName = function (state = init, action) { let newState = _.cloneDeep(state) // using lodash case 'ACTION_NAME': newState.a = 'c' return newState default: return state } 有
const init = {
a: 'b'
}
const reducerName = function (state = init, action) {
let newState = _.cloneDeep(state) // using lodash
case 'ACTION_NAME':
newState.a = 'c'
return newState
default:
return state
}
有一天我意识到,这可能是一种非常愚蠢的方法,因为每次触发动作时,我都会在每个减速器中创建一个新对象,即使状态根本不会改变
所以,我的同事给我发了丹·阿布拉莫夫的推特,他说没有必要深度克隆这个州。这让我思考,何时以及如何进行深度克隆
假设我在减速器中有这种状态:
const init = {
very: {
deeply: {
nested: 'string'
}
}
notSoDeeplyNested: 'string'
}
那么,以下哪一项是管理状态的正确方法/最接近正确方法:
(一)
(二)
(三)
最后一个似乎对我来说都不合适,但我很难理解这一点
所以,据我所知,至少每次都要做一个浅拷贝,但是什么时候我应该深度克隆某个东西,它应该是对象的哪一部分?我指的是哪一部分是第一级对象还是仅仅是嵌套的部分?回答你的问题:不,你没有深度克隆。相反,您可以选择性地浅复制需要更改的零件。在保留对未更改零件的现有引用的同时,可以使用“分解”仅以发生更改的路径为目标 在下面的示例中,它将
init
复制到一个对象,但将very
替换为一个新对象。非常
对象也是如此。它从init.very
复制所有内容,但用新值替换deep
case 'ACTION_NAME':
return {
...init,
very: {
...init.very,
deeply: action.deeply
}
};
在ES5中可以这样翻译:
case 'ACTION_NAME':
return Object.assign({}, init,
{very: Object.assign({}, init.very,
{deeply: action.deeply})});
最后,您有了一个新的状态对象,它部分由现有值和引用组成,部分由更改的值组成,类似于持久数据结构。我们更改了导致更改数据的对象,但并非所有对象都更改到可以称为深度克隆的程度
对于深层结构,它可能会变得冗长,但不是嵌套很深的结构。你说的“正确的方式”是什么意思?您是否关心性能、代码可读性等。?
const reducerName = function (state = init, action) {
case 'ACTION_NAME':
let newDeeply = _.cloneDeep(state.very.deeply)
let newState = Object.assign({}, state, { very: { deeply: newDeeply } ) // Cloning only the nested part, which actually changes?
newState.very.deeply = action.deeply
return newState
default:
return state
}
case 'ACTION_NAME':
return {
...init,
very: {
...init.very,
deeply: action.deeply
}
};
case 'ACTION_NAME':
return Object.assign({}, init,
{very: Object.assign({}, init.very,
{deeply: action.deeply})});