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

React使用useState修改对象数组时所有元素及原state同步变更问题

问题原因

该问题本质是JavaScript引用类型的共享引用特性导致的:

  • 对象、数组属于引用类型,你直接将接口返回的data.data同时赋值给product、variations初始元素,后续添加变体时也直接追加product本身,所有变量本质上都指向内存中的同一个对象
  • 修改任意一个引用指向的属性值,所有关联的变量都会同步变更,这就是修改单个变体价格时所有变体、原始product值同步变化的根本原因
解决方案

核心逻辑是每次使用基准product对象时都做深拷贝,切断引用关联,保证所有变体对象、原始product对象都是独立的内存地址:

  1. 初始化赋值时就做深拷贝,避免初始状态就共享引用
const [product, setProduct] = useState({} as any);
const [variations, setVariations] = useState([] as any);

useEffect(() => {
  const getProduct = async () => {
    const data = await axios.get("/products?id=4533843820679");
    // 深拷贝后赋值给product,作为不可变的基准模板
    setProduct(structuredClone(data.data));
    // 初始变体也使用独立的深拷贝对象,不和product共享引用
    setVariations([structuredClone(data.data)]);
  };
  getProduct();
}, []);
  1. 添加变体时,深拷贝基准product后再追加到数组
const handleAddVariation = () => {
  // 每次新增都生成独立的新变体对象,不影响原有对象
  const newVariation = structuredClone(product);
  setVariations(prev => [...prev, newVariation]);
}
  1. 修改变体属性时,也基于深拷贝生成新数组更新,避免直接修改原引用
const handlePriceChange = (variationIndex, newPrice) => {
  setVariations(prev => {
    const newVariations = structuredClone(prev);
    newVariations[variationIndex].variants.price = newPrice;
    return newVariations;
  })
}

补充说明:如果你的对象结构包含Date、函数、Symbol等特殊类型,structuredClone无法处理的场景,可以使用lodash的cloneDeep方法做深拷贝;如果是简单结构也可以用JSON.parse(JSON.stringify(obj))替代。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 06:27:02