React使用useState修改对象数组时所有元素及原state同步变更问题
问题原因
该问题本质是JavaScript引用类型的共享引用特性导致的:
- 对象、数组属于引用类型,你直接将接口返回的
data.data同时赋值给product、variations初始元素,后续添加变体时也直接追加product本身,所有变量本质上都指向内存中的同一个对象 - 修改任意一个引用指向的属性值,所有关联的变量都会同步变更,这就是修改单个变体价格时所有变体、原始
product值同步变化的根本原因
解决方案
核心逻辑是每次使用基准product对象时都做深拷贝,切断引用关联,保证所有变体对象、原始product对象都是独立的内存地址:
- 初始化赋值时就做深拷贝,避免初始状态就共享引用
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(); }, []);
- 添加变体时,深拷贝基准product后再追加到数组
const handleAddVariation = () => { // 每次新增都生成独立的新变体对象,不影响原有对象 const newVariation = structuredClone(product); setVariations(prev => [...prev, newVariation]); }
- 修改变体属性时,也基于深拷贝生成新数组更新,避免直接修改原引用
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
相关产品推荐
相关产品推荐

