我有一个包含2个子组件的主要组件。用于编辑图形的d3图形组件和表单组件。
数据从图形组件中的componentWillMount中的服务器加载。所有资源都表明应该在componentDidMount生命周期中加载数据。但是数据在render方法中用于呈现d3图的节点和链接。因此,如果我在componentDidMount中加载数据,则会抛出错误,因为我在此处映射数据。如何使用React处理它?</ p>
另一件令人粗略的事情是我查询数据库然后使用该数据来设置状态。我这样做是因为我需要更改一些数据。存储在数据库中的id不是线性排序的。如果ID为3的项目被删除,它就会消失。但是d3仍然想要id-number 3. d3不能跳过一个数字,比如说3,继续下一个数字,4。有没有更好的方法可以在不设置查询的情况下执行此操作?
当我使用表单向图表添加节点时,我需要刷新页面才能看到更改。我使用apollo的refetchQueries重新获取查询,但这不起作用。是否应该在componentDidUpdate中比较this.props和nextProp来重新渲染组件并查看更改而不刷新?
我知道这里有三个问题,那是因为我不确定哪个部分究竟会导致什么问题。我甚至不确定究竟是什么问题以及解决这些问题的可能方法。我希望你能给我一个关于如何处理上述事情之一的想法,所以我可以尝试新的东西。我正在努力学习如何编码,但在这个问题上独自一人确实有时会让它变得困难。
这是主要组成部分:
class Main extends Component {
render() {
const nodes = this.props.Nodes.nodes;
const relationships = this.props.Relationships.relationships;
if (!relationships) { return <div> </div> }
if (!nodes) { return <div> </div> }
return (
<div>
<Forms/>
<Graph nodes={nodes} rels={relationships} />
</div>
);
}
}
export default compose(
graphql(Relationships, {
name: "Relationships"
}),
graphql(Nodes, {
name: "Nodes"
})
)(Main);
这是Graph组件:
class Graph extends Component {
constructor(props) {
super(props);
this.state = { nodes: {}, links: {} };
}
loadData() {
const nodes = this.props.nodes;
const relationships = this.props.rels;
const graph = {};
graph.nodes = [];
graph.edges = [];
nodes.map(node => (
graph.nodes.push({ name: node.name, id: node.id, label: node.label })
));
relationships.map(rel => (
graph.edges.push({ source: parseInt(rel.source, 10), target: parseInt(rel.target, 10) })
));
const resetIds = [];
graph.edges.map(function (e) {
let sourceNode = graph.nodes.filter(function (n) {
return n.id === e.source;
})[0],
targetNode = graph.nodes.filter(function (n) {
return n.id === e.target;
})[0];
preedges.push({source: sourceNode, target: targetNode});
return preedges
});
this.setState({nodes: graph.nodes, links: resetIds });
}
componentWillMount(){
this.loadData();
}
componentDidMount() {
this.d3Graph = d3.select(ReactDOM.findDOMNode(this));
MYGRAPH.force = d3.forceSimulation(this.state.nodes)
.force("charge", d3.forceManyBody().strength(-50))
.force("link", d3.forceLink(this.state.links).distance(90))
.force("center", d3.forceCenter().x(MYGRAPH.width / 2).y(MYGRAPH.height / 2))
.force("collide", d3.forceCollide([30]).iterations([10]));
MYGRAPH.force.on('tick', () => {
this.d3Graph.call(MYGRAPH.updateGraph)
});
MYGRAPH.drag();
}
render() {
const nodes = this.state.nodes.map( (node) => {
return (
<Node
data={node}
label={node.label}
key={node.id}
/>);
});
const links = this.state.links.map( (link,i) => {
return (
<Link
key={link.target+i}
data={link}
/>);
});
return (
<div>
<svg width={MYGRAPH.width} height={MYGRAPH.height}>
<g >
{nodes}
</g>
<g >
{links}
</g>
</svg>
</div>
);
}
}
export default Graph;