You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React子组件修改props时意外篡改父组件state问题求助

问题根源
  • JavaScript 中数组和普通对象均为引用传递,执行x = p.p赋值时并未生成新的数组副本,x 与父组件 state 中的 portfolio 指向同一块内存地址,修改 x 内部的对象属性会直接变更原 state 数据
  • 浏览器控制台对引用类型的打印为懒求值逻辑,点击展开打印内容时才会读取当前内存中的最新值,因此即使 console.log 写在修改操作之前,最终展示的也是修改后的数据
解决方案

核心逻辑是提交 Firestore 前,对要操作的数据做拷贝,在副本上做字段修改,完全不触碰原始 props 数据,以下是三种适配不同场景的实现方案:

方案1:浅拷贝数组+单层对象拷贝(适配你的当前场景,性能最优)

你的持仓项均为单层基础属性,只需拷贝数组和第一层对象即可脱离原引用:

const makeDeal = () => {
  // 生成完全独立的副本
  const submitData = p.p.map(item => ({ ...item }));
  // 在副本上删除不需要提交的字段
  submitData.forEach(item => {
    delete item.price;
    delete item.name;
  });
  // 提交 submitData 到 Firestore 即可
}

方案2:全量深拷贝(适配持仓项含多层嵌套结构的场景)

如果持仓对象包含嵌套的数组/对象,可以用浏览器原生 structuredClone API 做全量深拷贝:

const makeDeal = () => {
  const submitData = structuredClone(p.p);
  submitData.forEach(item => {
    delete item.price;
    delete item.name;
  });
  // 后续提交逻辑
}

方案3:直接过滤字段生成提交数据(最稳妥)

无需做删除操作,生成提交数据时直接筛选需要存入数据库的字段,避免临时字段遗漏删除:

const makeDeal = () => {
  // 示例仅保留需要存入数据库的 id、持仓数量、成本三个字段,可按需调整
  const submitData = p.p.map(item => ({
    id: item.id,
    count: item.count,
    cost: item.cost
  }));
  // 直接提交即可
}

内容的提问来源于stack exchange,提问作者xoma_star

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 05:45:05