我正在处理一个包含react-graph-vis Graph
组件的React组件。我的组件应该呈现某个图形,并提供一个按钮,用于向图形添加节点。
我所做的简化版本是以下组件,它呈现(单个节点)图形和按钮。单击该按钮应该向图表添加第二个节点。
class GraphWrapper extends React.Component {
constructor(props) {
var graph = {nodes: [{id: 1, label: '1'}], edges: []};
this.state = {
options: {},
graph: graph
};
}
addNode() {
var graph = this.state.graph;
graph.nodes.push({id: 2, label: '2'});
this.setState({});
}
render() {
return <div>
<Graph graph={this.state.graph}, options={this.state.options}/>
<button onClick={this.addNode.bind(this)}>Add Node</button>
</div>;
}
}
初始图表正在正确呈现。此外,单击按钮可以按预期更改状态。但是,图形可视化不会发生变化,第二个节点也不会显示,尽管状态发生了变化,似乎<Graph/>
组件仍未被重新渲染。
我错过了什么?
答案 0 :(得分:4)
您应该始终将React状态视为不可变。在您的情况下,您正在改变状态,这意味着即使数组内容已更改,引用this.state.graph
和this.state.graph.nodes
也是相同的。
addNode
的更好版本:
addNode() {
var nodesCopy = this.state.graph.nodes.slice(); // this will create a copy with the same items
nodesCopy.push({id: 2, label: '2'});
this.setState({ graph: {nodes: nodesCopy, edges: []};);
}
请注意,由于您更改了nodes
引用,因为它现在指向一个新数组,因此您不得不将其级联,将每个引用更改为状态的根目录。
修改强>
在这个答案的前一个版本中,我暗示如果状态“引用”没有改变,React不会重新渲染。这是不正确的。 setState
将永远导致重新投降。 但,如果他们收到的道具没有更改,则各个组件可能会选择进行更新。
关于你的评论@snakile,你所描述的最可能的原因是Graph
组件以这样的方式实现了shouldComponentUpdate(nextProps, nextState),如果道具graph
的引用没有改变,那么组件不会更新。这可以解释为什么Graph
没有更新按钮的原因。