简体   繁体   English

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

[英]How to update a data of a node in d3 force layout using react

i am trying to creata a d3 force layout graph using react i am refering to this https://codepen.io/vialito/pen/RympKp example when i tried to update a data of the node the data is not reflecting in the data associated with the links and nodes gets disconnected from the links can anyone please help me out here is my following code. 我试图使用react创建d3力布局图,当我尝试更新未反映在关联数据中的节点数据时,我参考此https://codepen.io/vialito/pen/RympKp示例链接和节点与链接断开连接,任何人都可以帮助我,这是我的以下代码。

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>
        );
    }
}

thanks in advance 提前致谢

I couldn't see any detail on the update function, but I suspect it's returning the same array object. 我看不到有关更新功能的任何详细信息,但我怀疑它正在返回相同的数组对象。 So, when you do the comparison in componentDidUpdate, it wouldn't fire. 因此,当您在componentDidUpdate中进行比较时,它不会触发。

Here's a change to try - 这是要尝试的更改-

  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);

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM