在react项目里遇到一个情景:
修改redux里的一个数据,但是这个数据是对象下的对象下的对象,
一开始我是这样做的
export default (state = mario(), action) => {
let newState
// 能不能在这里进行newState = { ...state },每一次处理action
// 都会走一遍这个函数,下面试验一下
//这个是浅拷贝,只能复制对象里的非对象普通数据
// 但是里面的tracks是对象,还是指向的原来的tracks,里面的sequence就更没变了
newState = { ...state }
switch (action.type) {
case ADD_NOTE:
const { value, index, bucketId, trackId } = action.payload
const noteObj = { id: action.payload.id, value }
newState.tracks[trackId]
.sequence[bucketId].splice(index, 0, noteObj)
return newState
}
}
我的目的是,通过这个action,可以改变store的一个内部属性,页面会根据这个属性渲染相应的组件;
我当时以为newState已经通过扩展运算符复制了一个全新的state,在里面修改目标属性(比较深层),也能成功,
但实际上,我想达到的效果并没有实现,后来复盘一想,应该是深浅拷贝的问题,这种只能浅拷贝,遇到state里面还有对象的就只能复制地址了,
问题是,为什么无法实现目标,因为我这样修改是真的修改了,但是却因为是浅拷贝,举个例子来解释:
在store里面,我要修改的是state里的e,e处于非常内部的位置。
state{
a:1,
b:'2',
c: { d: {
e:'3',
}
}
这个时候,通过上述办法浅拷贝了一个newState,在newState里面修改e依旧是无法让store更新e,因为外部的c并不认为里面的e改变了,c只是一个地址,指向了这个对象,对象里面发生什么,c并不关心,action完成后,c对应的内部确实变了,但是页面渲染的时候react的diff算法并不会认为c有改变,所以不会渲染,
解决办法:
每次这种action都深拷贝,再整体返回这个深拷贝的newState,这种情况下就可以解决这个问题了
newState = JSON.parse(JSON.stringify(state))