通过 React.js 将 vis.js 网络渲染到容器中
Rendering vis.js network into container via React.js
如何将 vis.js 网络渲染到具体的 html 容器中?
我尝试了以下方法,但它不起作用:
<div id="network">
{new vis.Network("network", data, options)}
</div>
或者我应该按以下方式渲染它吗?
ReactDOM.render(<App />, document.getElementById('app'));
ReactDOM.render(<Network />, document.getElementById('network'));
虽然元素 "app" 和 "network" 在包装器 html 容器中。
我将不胜感激将 vis.js 网络渲染到根文档中的解决方案:
ReactDOM.render(<App />, document.getElementById('root'));
干杯!
这对我有用:
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
var data = {
nodes: nodes,
edges: edges
};
var options = {};
// initialize your network!
var VisNetwork = React.createClass({
componentDidMount(){
var network = new vis.Network(this.refs.myRef, data, options);
},
render: function() {
return <div ref="myRef"></div>;
}
});
ReactDOM.render(
<VisNetwork />,
document.getElementById('container')
);
从React 16.3开始,推荐使用React.createRef
Docs
正在用 16.3 风格更新@Gino 的回答。
import { DataSet, Network } from 'vis';
import React, { Component, createRef } from "react";
const nodes = new DataSet([
{ id: 1, label: 'Node 1' },
{ id: 2, label: 'Node 2' },
{ id: 3, label: 'Node 3' },
{ id: 4, label: 'Node 4' },
{ id: 5, label: 'Node 5' }
]);
// create an array with edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]);
const data = {
nodes: nodes,
edges: edges
};
const options = {};
// initialize your network!
class VisNetwork extends Component {
constructor() {
super();
this.network = {};
this.appRef = createRef();
}
componentDidMount() {
this.network = new Network(this.appRef.current, data, options);
}
render() {
return (
<div ref={this.appRef} />
);
}
}
我正在尝试做类似的事情,但我使用的是第三方库 (Apollo),它使用 React Hooks 并且在 class 组件中使用时出错,所以我切换到一个函数零件。 (我认为这与 class 没有钩子的组件有关,但是 Apollo 钩子用于从组件本身调用的函数中,所以我不太确定它们是如何组合在一起的。)
将 refs 与函数组件一起使用有点不同。我认为有一种方法可以使用 useEffect
挂钩来实现,但在我的特定用例中,我遇到了在渲染之前触发挂钩的问题(因为挂钩设置为在数据更改时触发,这是动态的)并且参考仍然不可用。
为了解决这个问题,一个解决方案似乎是使用 useCallback
挂钩,当从节点附加引用 to/detached 时会触发该挂钩。我基本上是从这里拿来的,它描述了具有类似前提条件的情况:https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node
我刚刚实现了它,所以我没有时间弄清楚到底发生了什么以及以后会发生什么,但是下面的设置方式应该会导致它在任何时候触发 data
更改(因为它在传递给 useCallback
的依赖项列表 [data]
中)。显然在这个例子中这不会发生,但我想我会把它留在里面。
请注意,这已根据我的具体示例进行了修改,我实际上没有 运行 下面的代码,因此可能存在一些错误,但我认为它应该为其他人指明正确的方向。
我是 React 的新手,所以我不太确定这是解决这个问题的最 appropriate/best/most 惯用方法,所以如果有人有任何额外的意见,我很想听听它。
import { DataSet, Network } from 'vis';
import React, { Component, createRef } from "react";
const nodes = new DataSet([
{ id: 1, label: 'Node 1' },
{ id: 2, label: 'Node 2' },
{ id: 3, label: 'Node 3' },
{ id: 4, label: 'Node 4' },
{ id: 5, label: 'Node 5' }
]);
// create an array with edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]);
const data = {
nodes: nodes,
edges: edges
};
const options = {};
// initialize your network!
const VisNetwork = () => {
const triggeredRef = React.useCallback( node => {
if ( node === null )
return;
const network = new Network(node, data, options);
}, [data]);
render() {
return (
<div ref={triggeredRef} />
);
}
}
这是一个使用函数式组件和 React 挂钩的现代示例。
package.json
{
"dependencies": {
"react": "16.13.0",
"react-dom": "16.13.0",
"vis-network": "7.4.0"
}
}
VisNetwork.js
import React, { useEffect, useRef } from 'react';
import { DataSet, Network} from 'vis-network/standalone/esm/vis-network';
const VisNetwork = () => {
// A reference to the div rendered by this component
const domNode = useRef(null);
// A reference to the vis network instance
const network = useRef(null);
// An array of nodes
const nodes = new DataSet([
{ id: 1, label: 'Node 1' },
{ id: 2, label: 'Node 2' },
{ id: 3, label: 'Node 3' },
{ id: 4, label: 'Node 4' },
{ id: 5, label: 'Node 5' }
]);
// An array of edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]);
const data = {
nodes,
edges
};
const options = {};
useEffect(
() => {
network.current = new Network(domNode.current, data, options);
},
[domNode, network, data, options]
);
return (
<div ref = { domNode } />
);
};
export default VisNetwork;
这是现代的 Typescript 方式:
import React, { useEffect, useRef } from "react";
import {
DataSet,
Network,
Options,
Data,
} from "vis-network/standalone/esm/vis-network";
export const LogicTreePanel = () => {
// A reference to the div rendered by this component
const domNode = useRef<HTMLDivElement>(null);
// A reference to the vis network instance
const network = useRef<Network | null>(null);
// An array of nodes
const nodes = new DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" },
{ id: 4, label: "Node 4" },
{ id: 5, label: "Node 5" },
]);
// An array of edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 },
]);
const data: Data = {
nodes,
edges,
};
const options: Options = {};
useEffect(() => {
if (domNode.current) {
network.current = new Network(domNode.current, data, options);
}
}, [domNode, network, data, options]);
return (
<div
ref={domNode}
/>
);
};
如何将 vis.js 网络渲染到具体的 html 容器中?
我尝试了以下方法,但它不起作用:
<div id="network">
{new vis.Network("network", data, options)}
</div>
或者我应该按以下方式渲染它吗?
ReactDOM.render(<App />, document.getElementById('app'));
ReactDOM.render(<Network />, document.getElementById('network'));
虽然元素 "app" 和 "network" 在包装器 html 容器中。
我将不胜感激将 vis.js 网络渲染到根文档中的解决方案:
ReactDOM.render(<App />, document.getElementById('root'));
干杯!
这对我有用:
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'},
{id: 5, label: 'Node 5'}
]);
// create an array with edges
var edges = new vis.DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
{from: 2, to: 5}
]);
var data = {
nodes: nodes,
edges: edges
};
var options = {};
// initialize your network!
var VisNetwork = React.createClass({
componentDidMount(){
var network = new vis.Network(this.refs.myRef, data, options);
},
render: function() {
return <div ref="myRef"></div>;
}
});
ReactDOM.render(
<VisNetwork />,
document.getElementById('container')
);
从React 16.3开始,推荐使用React.createRef
Docs
正在用 16.3 风格更新@Gino 的回答。
import { DataSet, Network } from 'vis';
import React, { Component, createRef } from "react";
const nodes = new DataSet([
{ id: 1, label: 'Node 1' },
{ id: 2, label: 'Node 2' },
{ id: 3, label: 'Node 3' },
{ id: 4, label: 'Node 4' },
{ id: 5, label: 'Node 5' }
]);
// create an array with edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]);
const data = {
nodes: nodes,
edges: edges
};
const options = {};
// initialize your network!
class VisNetwork extends Component {
constructor() {
super();
this.network = {};
this.appRef = createRef();
}
componentDidMount() {
this.network = new Network(this.appRef.current, data, options);
}
render() {
return (
<div ref={this.appRef} />
);
}
}
我正在尝试做类似的事情,但我使用的是第三方库 (Apollo),它使用 React Hooks 并且在 class 组件中使用时出错,所以我切换到一个函数零件。 (我认为这与 class 没有钩子的组件有关,但是 Apollo 钩子用于从组件本身调用的函数中,所以我不太确定它们是如何组合在一起的。)
将 refs 与函数组件一起使用有点不同。我认为有一种方法可以使用 useEffect
挂钩来实现,但在我的特定用例中,我遇到了在渲染之前触发挂钩的问题(因为挂钩设置为在数据更改时触发,这是动态的)并且参考仍然不可用。
为了解决这个问题,一个解决方案似乎是使用 useCallback
挂钩,当从节点附加引用 to/detached 时会触发该挂钩。我基本上是从这里拿来的,它描述了具有类似前提条件的情况:https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node
我刚刚实现了它,所以我没有时间弄清楚到底发生了什么以及以后会发生什么,但是下面的设置方式应该会导致它在任何时候触发 data
更改(因为它在传递给 useCallback
的依赖项列表 [data]
中)。显然在这个例子中这不会发生,但我想我会把它留在里面。
请注意,这已根据我的具体示例进行了修改,我实际上没有 运行 下面的代码,因此可能存在一些错误,但我认为它应该为其他人指明正确的方向。
我是 React 的新手,所以我不太确定这是解决这个问题的最 appropriate/best/most 惯用方法,所以如果有人有任何额外的意见,我很想听听它。
import { DataSet, Network } from 'vis';
import React, { Component, createRef } from "react";
const nodes = new DataSet([
{ id: 1, label: 'Node 1' },
{ id: 2, label: 'Node 2' },
{ id: 3, label: 'Node 3' },
{ id: 4, label: 'Node 4' },
{ id: 5, label: 'Node 5' }
]);
// create an array with edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]);
const data = {
nodes: nodes,
edges: edges
};
const options = {};
// initialize your network!
const VisNetwork = () => {
const triggeredRef = React.useCallback( node => {
if ( node === null )
return;
const network = new Network(node, data, options);
}, [data]);
render() {
return (
<div ref={triggeredRef} />
);
}
}
这是一个使用函数式组件和 React 挂钩的现代示例。
package.json
{
"dependencies": {
"react": "16.13.0",
"react-dom": "16.13.0",
"vis-network": "7.4.0"
}
}
VisNetwork.js
import React, { useEffect, useRef } from 'react';
import { DataSet, Network} from 'vis-network/standalone/esm/vis-network';
const VisNetwork = () => {
// A reference to the div rendered by this component
const domNode = useRef(null);
// A reference to the vis network instance
const network = useRef(null);
// An array of nodes
const nodes = new DataSet([
{ id: 1, label: 'Node 1' },
{ id: 2, label: 'Node 2' },
{ id: 3, label: 'Node 3' },
{ id: 4, label: 'Node 4' },
{ id: 5, label: 'Node 5' }
]);
// An array of edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 }
]);
const data = {
nodes,
edges
};
const options = {};
useEffect(
() => {
network.current = new Network(domNode.current, data, options);
},
[domNode, network, data, options]
);
return (
<div ref = { domNode } />
);
};
export default VisNetwork;
这是现代的 Typescript 方式:
import React, { useEffect, useRef } from "react";
import {
DataSet,
Network,
Options,
Data,
} from "vis-network/standalone/esm/vis-network";
export const LogicTreePanel = () => {
// A reference to the div rendered by this component
const domNode = useRef<HTMLDivElement>(null);
// A reference to the vis network instance
const network = useRef<Network | null>(null);
// An array of nodes
const nodes = new DataSet([
{ id: 1, label: "Node 1" },
{ id: 2, label: "Node 2" },
{ id: 3, label: "Node 3" },
{ id: 4, label: "Node 4" },
{ id: 5, label: "Node 5" },
]);
// An array of edges
const edges = new DataSet([
{ from: 1, to: 3 },
{ from: 1, to: 2 },
{ from: 2, to: 4 },
{ from: 2, to: 5 },
]);
const data: Data = {
nodes,
edges,
};
const options: Options = {};
useEffect(() => {
if (domNode.current) {
network.current = new Network(domNode.current, data, options);
}
}, [domNode, network, data, options]);
return (
<div
ref={domNode}
/>
);
};