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

为何_.remove会修改原数组?useState数组同步变更问题

问题原因与解决方案

为什么原数组会被同步修改?

  • JavaScript里数组属于引用类型,const newArray = backendArray;这行代码并没有创建新的数组,只是让newArray和backendArray指向内存中同一个数组对象。两个变量共享同一个引用,操作其中一个就等于直接操作原数组。
  • 另外,_.remove方法的特性是直接修改调用它的原数组,它会从目标数组中移除符合条件的元素,同时返回被移除的元素。你用它操作newArray,本质上就是在修改backendArray指向的那个数组。

怎么解决?

你需要先创建原数组的独立副本,再对副本进行操作,切断和原数组的引用关联:

1. 浅拷贝(适用于数组元素是基本类型或不需要修改嵌套对象的场景)

可以用扩展运算符或Array.from()创建副本:

const [backendArray, setBackendArray] = useState([{/* some values */}])

useEffect(() => {
  // 创建原数组的浅拷贝副本
  const newArray = [...backendArray];
  // 对副本执行移除操作
  const arrayForPurpose1 = _.remove(newArray, n => n.value != null);
  // 此时backendArray不会被修改,newArray是移除后的结果
}, [backendArray]);

2. 深拷贝(适用于数组元素是嵌套对象,需要完全切断所有引用的场景)

如果数组里的元素是嵌套对象,浅拷贝只会复制对象的引用,修改副本里的对象还是会影响原数组。这时可以用lodash的_.cloneDeep做深拷贝:

const [backendArray, setBackendArray] = useState([{/* some values */}])

useEffect(() => {
  // 创建原数组的深拷贝副本
  const newArray = _.cloneDeep(backendArray);
  const arrayForPurpose1 = _.remove(newArray, n => n.value != null);
}, [backendArray]);

更简洁的替代方案

如果你的需求只是筛选出value != null的元素,完全可以用_.filter替代_.remove——它不会修改原数组,直接返回符合条件的新数组,代码更安全简洁:

const [backendArray, setBackendArray] = useState([{/* some values */}])

useEffect(() => {
  const arrayForPurpose1 = _.filter(backendArray, n => n.value != null);
  // 原backendArray完全不受影响
}, [backendArray]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 12:35:19