Javascript parse(JSON.stringify(state))是否保证redux状态不会发生突变?

Javascript parse(JSON.stringify(state))是否保证redux状态不会发生突变?,javascript,json,reactjs,redux,state,Javascript,Json,Reactjs,Redux,State,我一直在跟踪一个问题,其中redux存储正确更新,但组件没有反映更改。我尝试了多种方法来确保我没有改变状态,但问题依然存在。我的减速器通常采用以下形式: case 'ADD_OBJECT_TO_OBJECT_OF_OBJECTS': { newState = copyState(state); newState.objectOfObjects[action.id] = action.obj; return newState; } 对于copyState函数,我通常使用嵌

我一直在跟踪一个问题,其中redux存储正确更新,但组件没有反映更改。我尝试了多种方法来确保我没有改变状态,但问题依然存在。我的减速器通常采用以下形式:

case 'ADD_OBJECT_TO_OBJECT_OF_OBJECTS': {
    newState = copyState(state);
    newState.objectOfObjects[action.id] = action.obj;
    return newState;
}
对于copyState函数,我通常使用嵌套的Object.assign()调用,但避免错误并不是那么简单。对于测试,为了确保我没有改变状态,使用它正确吗

const copyState = (state) => {
    return JSON.parse(JSON.stringify(state));
};
作为一种保证不改变(redux)状态的方法,不管过程有多昂贵

如果没有,是否有其他深度复制方法可以确保我没有变异状态

编辑: 考虑到其他人可能也有同样的问题,我将转达我遇到的问题的解决方案

我试图调度一个操作,然后在后面的一行中,我试图访问前一行中更新的存储中的数据

dispatchAction(data) // let's say this updates a part of the redux state called 'collection'
console.log(this.props.collection) // This will not be updated!

请参阅

是这会进行深度克隆,而不管成本有多高。难点(正如问题下的评论所暗示的)是确保
状态
在其他地方保持不变

由于您要求使用其他方法,而这不适合作为评论,因此我建议看一看,这消除了跟踪状态突变错误的问题(但可能有其自身的局限性):

copyState()函数不会改变您的状态。很好。对于阅读这个问题的其他人来说,直接去也可以

const newState = JSON.parse(JSON.stringify(oldState));
得到一份深度拷贝。感觉不干净,但这样做是可以的

您没有看到订阅运行的原因可能是Redux在复制新状态(reducer函数的输出)之前将其与现有状态进行比较。如果没有差异,它不会触发任何订阅。因此,我们从不直接改变状态,而是返回一个副本——如果我们改变了状态,变化将永远不会被检测到


另一个原因可能是,我们不知道代码中的dispatchAction()到底做了什么。如果它是异步的(可能是因为中间件的缘故?),那么在下一行的console.log()之后才会应用更改。

state
将在
copyState
中保持不变,可以(但难以置信的愚蠢)给
state
一个
.toJSON
方法对其进行修改。谢谢您的回答。但是我想确保我对redux没有根本性的误解。您提到“确保状态在其他任何地方都保持不变。”为了测试,我在每个减速机中都使用了这个JSON.parse()方法。尽管如此,存储仍会正确更新(中间件在动作分派后在“nextState”中显示更改),但组件不会反映这些更改。这是否意味着问题肯定不是redux需要非变异状态,或者我对redux在copyState实现中的工作方式有误解?根据现有信息,我认为您没有误解。。。我希望我不是:)我也是redux的初学者,但我们可以放心地说,您的
copyState
函数提供了正确的保证(无论其性能如何)。因此,问题似乎在别处:/我还建议使用
lodash
中的
deepCopy
而不是
JSON.parse(JSON.stringify(state))
方法,主要是因为lodash的deepCopy在
parse(stringify(state))时保留
Date
对象
将为您留下字符串,而不是
日期
对象。
const newState = JSON.parse(JSON.stringify(oldState));