需要保留原始数组值并创建副本,更改副本中的一个值但原始值也被更改?

Need to keep original array values and create copy, change one value in copy but original is changed also?

我正在使用 react/redux 来获取数据等

const dates = useSelector((state) => state.holidays.holidays);
const [newDates, setNewDates] = useState(null);

useEffect(() => {
    dispatch(getAllHolidays());
}, []);

useEffect(() => {
    if (dates) {
        setNewDates([...dates]);
    }
}, [dates]);  

所以我正在使用“useSelector”从我的 Redux/state 组件中获取数据。 然后我使用“useState”在其中保留日期的副本。 第一个“useEffect”将在组件 mount/start.
上获取我需要的数据 第二个“useEffect”将填写日期的副本,每次日期更改(状态)。

无论如何,每当我现在更改“newDates”值并对“dates”数组执行 console.log 时,所有内容也会发生变化...我认为使用扩展器运算符会创建一个新数组(所以之前没有引用“dates”-array,然后用“dates”-array 的所有对象填充它。但似乎不是这样?

例如,我是这样使用它的:

const handleDateDescriptionChange = (id, event) => {
    let newDatesArray = [...newDates];
    newDatesArray.find(date => date.id === id).description = event.target.value;
    console.log(dates.find(x => x.id === id).description);
    setNewDates([...newDatesArray]);
}

const deleteDateChanges = (id) => {
    newDates.find(x => x.id === id).description = dates.find(x => x.id === id).description;
    console.log(newDates.find(x => x.id === id).description);
    console.log(dates.find(x => x.id === id).description);
    setNewDates([...newDates]);
}  

在第一个函数中,我想更改对象的值(具有相应的 ID)以将其“描述”的值设置为用户在 TextField 中输入的任何内容。 所以为了确定,我在本地创建了一个新的数组副本(没有引用以前的),然后找到我需要的对象(基于 id),然后更改它的“描述”值。

然后我console.log原始的“日期”数组,它也被修改了!!

在第二个函数中,我试图将修改后的“描述”值重置为“日期”数组中的原始值,但这是不可能的,因为“日期”数组也已更改并且值是一样的,所以第二个函数现在在功能上什么都不做。

我是不是遗漏了什么?!

这是因为heap中存放了一个数组。数组是引用类型,因此如果您尝试将数组分配给新数组,新数组将不是副本。它将引用数组存储在heap.

real 复制数组的最简单方法之一是遍历数组并将每个值单独分配给新数组。因此,新数组拥有自己的 heap 存储位置,但与原始数组具有相同的值。

如果你对这个话题更感兴趣,这里有一个很好的解释: Link

浅拷贝只在操作的根级别起作用,所有嵌套更深的对象仍然是对原始对象的引用。您必须浅复制所有正在更新的嵌套状态以避免状态突变。

const handleDateDescriptionChange = (id, event) => {
  // use array.map to shallow copy the array
  setNewDates(dates => dates.map(date => date.id === id ? {
    ...date, // <-- shallow copy date if id match
    description: event.target.value
  } : date)); // <-- otherwise return original since no update
}

const deleteDateChanges = (id) => {
  // use array.filter to shallow copy array and remove elements
  setNewDates(dates => dates.filter(date => date.id !== id));
}