如何使用 Cytoscape.js 创建功能性 React 组件?
How to create a Functional React Component using Cytoscape.js?
我正在使用 Cytoscape.js 和 React。我有一个功能性的 GraphComponent,它接收用于呈现 Cytoscape 图的元素列表,以及我希望设置动画的节点列表。
我遇到的问题是我不知道如何保留 'cy' 对象以便以后可以访问它。具体来说,我想向路径中的节点添加一个 class。
const MyComponent = ({ myElements, path }) => {
useEffect(() => {
const cy = {
...
elements: myElements
...
}
}, []);
useEffect(() => {
// This fails since 'cy' is undefined
cy.$id("A").addClass("highlighted");
}, [path]);
return (
<div id="cy" />
);
}
想法 #1:创建一个变量 'cy' 然后我可以在 useEffect 中设置值。
问题:初始渲染后 'cy' 的值丢失
const MyComponent = ({ myElements, path }) => {
let cy;
useEffect(() => {
cy = {
...
elements: myElements
...
}
}, []);
useEffect(() => {
// This fails since 'cy' is undefined
cy.$id("A").addClass("highlighted");
}, [path]);
return (
<div id="cy" />
);
}
想法 #2:将 cy 保存为状态。
问题:Cy 未正确初始化
const MyComponent = ({ myElements, path }) => {
const [cy, setCy] = useState({});
useEffect(() => {
setCy({
...
elements: myProp
...
});
}, []);
useEffect(() => {
cy.$id("A").addClass("highlighted");
}, [path]);
return (
// This fails since cy is not initialized to a cytoscape object when component mounts
<div id="cy" />
);
}
所以问题是,如何在 React 功能组件中创建和访问 cytoscape 对象(并修改其节点和元素)?
您通常不想在状态中存储道具,因为您已经将其存储在其他地方。如果您通过道具为 cy 传递数据,只需使用道具。
一般来说,如果您尝试根据外部更改保持状态更新,则需要向 useEffect
挂钩添加依赖项。一个空数组意味着效果只会 运行 一次,在挂载时。
参考文档以获得很好的教程,但通常它是这样工作的:
useEffect(()=> {
setSomeState(/* set state */)
}, [someValue])
如果 someValue
保持不变,则效果不会 re-run。如果它发生变化,效果将 运行 下次渲染时(由于道具或状态变化)。
同样,如果数据是通过 prop 传入的,请不要将其设置为状态。如果您想跟踪基于该 prop 的组件内部的某些内容,那么 useEffect 和对 prop 的依赖将为您解决这个问题。
编辑评论
声明是在渲染之间保存数据的位置。如果问题是你不应该渲染,因为挂载上没有值(但会在另一个渲染中),那么将它包装在一个表达式中,例如,
{someValueOrExpression ? <div id="cy" /> : <div>Empty State</div>}
或
{someValueOrExpression && <div id="cy" />}
这样 div 就不会显示和失败,直到它具有正确呈现所需的内容。
我正在使用 Cytoscape.js 和 React。我有一个功能性的 GraphComponent,它接收用于呈现 Cytoscape 图的元素列表,以及我希望设置动画的节点列表。
我遇到的问题是我不知道如何保留 'cy' 对象以便以后可以访问它。具体来说,我想向路径中的节点添加一个 class。
const MyComponent = ({ myElements, path }) => {
useEffect(() => {
const cy = {
...
elements: myElements
...
}
}, []);
useEffect(() => {
// This fails since 'cy' is undefined
cy.$id("A").addClass("highlighted");
}, [path]);
return (
<div id="cy" />
);
}
想法 #1:创建一个变量 'cy' 然后我可以在 useEffect 中设置值。
问题:初始渲染后 'cy' 的值丢失
const MyComponent = ({ myElements, path }) => {
let cy;
useEffect(() => {
cy = {
...
elements: myElements
...
}
}, []);
useEffect(() => {
// This fails since 'cy' is undefined
cy.$id("A").addClass("highlighted");
}, [path]);
return (
<div id="cy" />
);
}
想法 #2:将 cy 保存为状态。
问题:Cy 未正确初始化
const MyComponent = ({ myElements, path }) => {
const [cy, setCy] = useState({});
useEffect(() => {
setCy({
...
elements: myProp
...
});
}, []);
useEffect(() => {
cy.$id("A").addClass("highlighted");
}, [path]);
return (
// This fails since cy is not initialized to a cytoscape object when component mounts
<div id="cy" />
);
}
所以问题是,如何在 React 功能组件中创建和访问 cytoscape 对象(并修改其节点和元素)?
您通常不想在状态中存储道具,因为您已经将其存储在其他地方。如果您通过道具为 cy 传递数据,只需使用道具。
一般来说,如果您尝试根据外部更改保持状态更新,则需要向 useEffect
挂钩添加依赖项。一个空数组意味着效果只会 运行 一次,在挂载时。
参考文档以获得很好的教程,但通常它是这样工作的:
useEffect(()=> {
setSomeState(/* set state */)
}, [someValue])
如果 someValue
保持不变,则效果不会 re-run。如果它发生变化,效果将 运行 下次渲染时(由于道具或状态变化)。
同样,如果数据是通过 prop 传入的,请不要将其设置为状态。如果您想跟踪基于该 prop 的组件内部的某些内容,那么 useEffect 和对 prop 的依赖将为您解决这个问题。
编辑评论
声明是在渲染之间保存数据的位置。如果问题是你不应该渲染,因为挂载上没有值(但会在另一个渲染中),那么将它包装在一个表达式中,例如,
{someValueOrExpression ? <div id="cy" /> : <div>Empty State</div>}
或
{someValueOrExpression && <div id="cy" />}
这样 div 就不会显示和失败,直到它具有正确呈现所需的内容。