react-graph-vis 中的 Graph 组件在状态改变时不会重新加载

The Graph component in react-graph-vis doesn't reload when the state changes

我正在开发一个包装 react-graph-visGraph 组件的 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/> 组件似乎没有被重新渲染,尽管状态发生了变化。

我错过了什么?

你应该始终将 React 状态视为不可变的。在您的情况下,您正在改变状态,这意味着即使数组内容已更改,引用 this.state.graphthis.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 引用,因为现在它指向一个新数组,您被迫将其级联,更改每个引用直到状态的根。

编辑

在这个答案的前一个版本中,我暗示如果状态 "references" 没有改变,React 不会重新渲染。那是不正确的。 setState 将始终导致重新渲染。 但是,个别组件可能选择不更新,如果他们收到的道具没有改变。

关于你的评论@snakile,你所描述的最可能的原因是 Graph 组件以这样的方式实现了 shouldComponentUpdate(nextProps, nextState),如果道具的引用 graph 没有改变,那么组件就不会更新。这可以解释为什么您的按钮更新而 Graph 没有更新。