如何使用react在d3强制布局中更新节点的数据

时间:2018-09-19 10:30:33

标签: javascript reactjs d3.js

我尝试使用react创建d3力布局图,当我尝试更新节点的数据时该数据未反映在与链接和节点关联的数据中,因此我参考此What is the use of DesiredCapabilities in Selenium WebDriver?示例与链接断开连接,任何人都可以帮助我,这是我的以下代码。

export default class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      addLinkArray: [],
      name: "",
      nodes:
        [
          {"name": "fruit", "id": 0},
          {"name": "apple", "id": 1},
          {"name": "orange", "id": 2},
          {"name": "banana", "id": 3}
        ],
      links:
        [
          {"source": 0, "target": 1, "id": 0},
          {"source": 0, "target": 2, "id": 1}
        ]
      }
    this.handleAddNode = this.handleAddNode.bind(this)
    this.addNode = this.addNode.bind(this)
    this.handleDelete = this.handleDelete.bind(this)
    this.handleUpdate = this.handleUpdate.bind(this)
    this.updateFlag = "";
  }

    componentDidMount() {

        const data = this.state;
            FORCE.initForce(data.nodes, data.links)
                FORCE.tick(this)
                FORCE.drag()
        console.log("after mount",this.state.links);
    }

    componentDidUpdate(prevProps, prevState) {
        if ((prevState.nodes !== this.state.nodes || prevState.links !== this.state.links)) {
            const data = this.state;
                console.log("comp update");
                console.log(this.state.nodes);
                console.log(this.state.links);

                FORCE.initForce(this.state.nodes,this.state.links);
                FORCE.tick(this);
                FORCE.drag();
                this.updateFlag = "";
        }

    }
    componentWillMount() {
      console.log("before mount",this.state.links);
    }

  handleAddNode(e) {
        this.setState({ [e.target.name]: e.target.value });
    }

  addNode(e) {
        e.preventDefault();
        this.setState(prevState => ({
            nodes: [...prevState.nodes, { name:this.state.name, id: prevState.nodes.length + 1, }], name: ''
        }));
        this.updateFlag = "created";
    }
    handleDelete() {
      this.setState(prevState=>({
        links:prevState.links.filter((node,i)=>{
          return i != 0
        }),
        nodes:prevState.nodes.filter((node,i)=>{
          return i != 1
        })
      }))
      this.updateFlag = "deleted";
    }
    handleUpdate() {
      const state2 = update(this.state.nodes, {0: {name: {$apply: function(x){ return "fruit2"}}}});

      this.setState({
        nodes : state2
      })
      console.log("this",this.state.links);
      //FORCE.initForce(this.state.nodes,this.state.links);

    }

    render() {
        var links = this.state.links.map( (link) => {
            return (
                <Link
                    key={link.id}
                    data={link}
                />);
        });
        var nodes = this.state.nodes.map( (node) => {
              return (
              <Node
                  data={node}
                  name={node.name}
                  key={node.id}
              />);
          });
        return (
          <div className="graph__container">
            <form className="form-addSystem" onSubmit={this.addNode.bind(this)}>
              <h4 className="form-addSystem__header">New Node</h4>
              <div className="form-addSystem__group">
                <input value={this.state.name} onChange={this.handleAddNode.bind(this)}
                  name="name"
                  className="form-addSystem__input"
                  id="name"
                  placeholder="Name"/>
                <label className="form-addSystem__label" htmlFor="title">Name</label>
              </div>
              <div className="form-addSystem__group">
                <input className="btnn" type="submit" value="add node" />
                <input className="btnn" onClick = {this.handleDelete} type="button" value="delete" />
                <input className="btnn" onClick = {this.handleUpdate} type="button" value="update" />
              </div>
            </form>
            <svg className="graph" width={FORCE.width} height={FORCE.height}>
                <g>
                    {links}
                </g>
                <g>
                    {nodes}
                </g>
            </svg>
          </div>
        );
    }
}

预先感谢

1 个答案:

答案 0 :(得分:0)

我看不到有关更新功能的任何详细信息,但我怀疑它正在返回相同的数组对象。因此,当您在componentDidUpdate中进行比较时,它不会触发。

这里是要尝试的更改-

  handleUpdate() {
        const state2 =[...this.state.nodes]
        state2[0].name="fruit2";

        this.setState({
          nodes : state2
        })
        console.log("this",this.state.links);
        //FORCE.initForce(this.state.nodes,this.state.links);

}