我正在使用带有自定义节点元素的 React d3 树。我试图在悬停节点时显示一些文本,但它仅在我第一次悬停在一个节点上时有效,然后每次悬停节点时 mouse.currentTarget 似乎为空,因此 Documentation.show 不会设置为真的。 使用 useMemo 以便每次我将鼠标悬停在节点上时整个组件不会重新渲染(因为文档状态发生变化)。
import Tree, { TreeNodeDatum } from "react-d3-tree";
const [documentation, setDocumentation] = useState({
x: 0,
y: 0,
show: false,
text: "test text.",
});
const TreeMemo = useMemo(() => {
const renderCustomNode = ({
nodeDatum,
toggleNode,
}: {
nodeDatum: TreeNodeDatum;
toggleNode: () => void;
}) => (
<g>
<circle
r="15"
onMouseEnter={(mouse) =>
setDocumentation((prevState) => {
return mouse.currentTarget
? {
x:
mouse.clientX -
mouse.currentTarget.getBoundingClientRect().right,
y:
mouse.clientY -
mouse.currentTarget.getBoundingClientRect().top,
show: true,
text: prevState.text,
}
: prevState;
})
}
onMouseLeave={() => {
setDocumentation((prevState) => {
return {
...prevState,
show: false,
};
});
}}
onClick={toggleNode}
/>
<text fill="black" strokeWidth="1" x="20">
{nodeDatum.name}
</text>
{nodeDatum.attributes?.department && (
<text fill="black" x="20" dy="20" strokeWidth="1">
Department: {nodeDatum.attributes?.department}
</text>
)}
</g>
);
return (
<Tree
key={triggerRecenter}
data={orgChart}
translate={treeTranslate}
dimensions={
treeContainerRef.current
? {
height: treeContainerRef.current.getBoundingClientRect().height,
width: treeContainerRef.current.getBoundingClientRect().width,
}
: undefined
}
renderCustomNodeElement={(rd3tProps) =>
renderCustomNode({ ...rd3tProps })
}
orientation="vertical"
/>
);
}, [triggerRecenter, treeTranslate]);
在 useMemo deps 中添加文档状态使其可以工作,但会触发整个组件的重新渲染,这是不需要的。 还使用 onMouseMove 似乎有效,但它使位置发生变化。
通过将 onMouseEnter 处理程序更改为下面来解决。根据我的理解,这似乎阻止了 currentTarget 为空,如果我错了请纠正我。
onMouseEnter={(event) => {
const { clientX, clientY, currentTarget } = event;
const { right, top } = currentTarget.getBoundingClientRect();
setDocumentation((prevState) => {return {
x: clientX - right,
y: clientY - top,
show: true,
text: prevState.text,
}});
}}