操作数组副本(通过扩展运算符创建)更改内存中的原始数组

https://codesandbox.io/s/chart-3yx8p

“图表”组件由 3 个图表层叠而成:

  • 折线图 - “VictoryLine”组件

  • 2 个散点图 - “VictoryScatter”组件

折线图只是呈现线。第一个散点图在线上的每个点上呈现蓝色圆圈 - 我们将其称为“BlueScatter”。这两个接收相同的静态数据。第二个散点图呈现底部的黑点 - 我们将其称为“BlackScatter”。BlackScatter 的数据处于需要更改的状态。

每当您将鼠标悬停在其中一个蓝色圆圈上时,会发生两件事:

  • 显示工具提示

  • 圆圈下方的黑点向上移动了一半

当您的鼠标离开圆圈时,工具提示消失,点将向下移动。然而后者并没有发生......

当您将鼠标悬停在一个圆圈上时,传递给该圆圈标签组件的“活动”道具将设置为 true - 当您的鼠标离开时设置为 false。“Tooltip”组件设置为 BlueScatter 上每个点的标签,因此 Tooltip 接收此 prop。Tooltip 只是一个不可见的 SVG,用于锚定 Material UI 工具提示。BlueScatter 的事件处理程序控制此逻辑(请参阅常量文件)。在 Tooltip 中,我使用从 Chart 传递的 props 来更改该索引处 BlackScatter 数据的坐标。

综上所述:
在图表中,我将 INITIAL_HOVER_DATA 传播到状态数组中以设置 BlackScatter 的数据。在 Tooltip 中,我再次将该常量扩展到一个空数组中,以便在以下 if 语句中使用。过去我一直能够使用扩展运算符来制作数组的副本 - 但由于某种原因,工具提示中的第 14 行似乎正在操纵内存中的原始常量。这就是为什么黑点不回到原来的位置。为什么会这样?取消注释第 16 行会使事情按预期工作,但理论上不需要它。

顺便说一句——如果有人能提出更好的方法来实现同样的功能,我会很高兴收到反馈!

TLDR:操作 INITIAL_HOVER_DATA 数组的副本会更改内存中的原始数组。


POPMUISE
浏览 45回答 1
1回答

缥缈止盈

问题即使您浅复制数组,newHoverData[index].y = yValue / 2;也是状态突变,因为您没有同时复制每个更新的元素。每个元素仍然引用原始数组中的元素。解决方案浅拷贝数组和要更新的元素useEffect(() => {  const { y: yValue } = data[index];  setScatterHoverData(    INITIAL_HOVER_DATA.map((el, i) =>      i === index && active        ? {            ...el,            y: yValue / 2          }        : el    )  );}, [active]);
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript