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 数组的副本会更改内存中的原始数组。
1 回答

缥缈止盈
TA贡献2041条经验 获得超4个赞
问题
即使您浅复制数组,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]);
添加回答
举报
0/150
提交
取消