React开发报错:尝试为不可变冻结对象设置属性如何解决?
React不可变对象修改报错解决方案
你遇到的报错核心原因是React的state设计为不可变,不允许直接修改state返回的对象属性:
you tried to modify 'status' key of an immutable object.
问题复盘
你第一次的代码直接将state中的manager对象传入service层修改,属于直接修改React原state对象,必然触发报错。
你修改为传入浅拷贝{...manager}后依旧报错,可按照以下步骤排查解决:
具体解决步骤
步骤1:排查其他直接修改原state的逻辑
检查全量代码中是否存在其他位置直接对manager.status赋值、或是将原manager对象传入其他方法进行属性修改的逻辑,只要有一处直接修改原state,就会触发该报错。步骤2:调整状态修改逻辑,收敛到组件侧
更符合React开发规范的写法是将不可变更新的逻辑放在组件侧,service层仅处理业务逻辑(如接口请求),不要修改入参对象:
App.js 调整后代码
const data = {name: 'John', status:'employed' }; const [manager, updateManager] = useState(data); const updateStatus = async () => { // 直接在组件侧生成全新的状态对象 const newManager = {...manager, status: 'employed'}; await service.setStatus(newManager); updateManager(newManager); }
service.js 调整后代码
setStatus(manager){ // 仅处理业务逻辑,不修改入参 // 原有修改入参属性的逻辑删除 return manager; }
- 步骤3:嵌套对象场景使用深拷贝
如果后续你的manager对象存在多层嵌套属性,浅拷贝{...manager}仅能复制第一层属性,深层属性依旧引用原state的对象,修改时依旧会报错,此时可以用浏览器原生的structuredClone方法做深拷贝:
const newManager = structuredClone(manager); newManager.status = 'employed'; await service.setStatus(newManager); updateManager(newManager);
- 步骤4:适配不可变相关依赖规则
如果你的项目开启了React严格模式,或是集成了Immer、Immutable.js等不可变状态管理库,需要按照对应工具的规则修改状态,比如Immer需要用produce方法包裹状态修改逻辑。
内容的提问来源于stack exchange,提问作者ruth hadish
相关产品推荐
相关产品推荐

