admin管理员组

文章数量:1026989

I am using some d3 for visualization and decided to also use reactstrap. Basically clicking a circle in d3 will result in the reactstrap element Collapse to appear.

I am not finding any luck with setState... I am doing all my react code in ponenetDidMount(), inside of ponentDidMount(), I have a function update(), and in update, I have a function called click, and when click triggers, it does:

this.setState({ collapse: !this.state.collapse });

It doesn't work, and I lack the fundamental JS to reason why, I am assuming that the this keyword is referring to the function update instead of my ponent "Tree"?

Code:

import React, { Component } from "react";
import * as d3 from "d3";
import { hierarchy, tree } from "d3-hierarchy";

import { Collapse, Button, CardBody, Card } from "reactstrap";

class Tree extends Component {
  constructor(props) {
    super(props);
    this.state = { collapse: false };
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
    //this.toggle = this.toggle.bind(this);
  }

  ponentDidMount() {
    this.updateWindowDimensions();


    // Set the dimensions and margins of the diagram
    var height1 = window.innerHeight;
    var margin = { top: 10, right: 90, bottom: 30, left: 180 },
      width = 1080 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    // appends a 'group' element to 'svg'
    // moves the 'group' element to the top left margin
    var svg = d3
      .select("body")
      .append("svg")
      .attr("width", window.innerWidth - margin.right - margin.left)
      .attr("height", window.innerHeight - margin.top - margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var i = 0,
      duration = 500,
      root;

    // declares a tree layout and assigns the size
    var treemap = d3.tree().size([window.innerHeight, window.innerWidth]);

    root = d3.hierarchy(treeData, function(d) {
      return d.children;
    });
    root.x0 = height / 2;
    root.y0 = 0;

    // Collapse after the second level
    root.children.forEach(collapse);

    update(root);

    // Collapse the node and all it's children
    function collapse(d) {
      if (d.children) {
        d._children = d.children;
        d._children.forEach(collapse);
        d.children = null;
      }
    }

    function update(source) {
      // Assigns the x and y position for the nodes

      var treeData = treemap(root);

      // Compute the new tree layout.
      var nodes = treeData.descendants(),
        links = treeData.descendants().slice(1),
        more_button = treeData.descendants();

      // Normalize for fixed-depth.
      nodes.forEach(function(d) {
        d.y = d.depth * 360;
      });

      // ****************** Nodes section ***************************

      // Update the nodes...
      var node = svg.selectAll("g.node").data(nodes, function(d) {
        return d.id || (d.id = ++i);
      });

      // Enter any new modes at the parent's previous position.
      var nodeEnter = node
        .enter()
        .append("g")
        .attr("class", "node")

        //if deleted, bubbles e from the very top, is weird
        .attr("transform", function(d) {
          return "translate(" + source.y0 + "," + source.x0 + ")";
        });

      // Add Circle for the nodes
      nodeEnter
        .append("circle")
        .attr("class", "node")
        .attr("r", 1e-6)
        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        });

      /*
// Add labels for the nodes
      nodeEnter
        .append("text")
        .attr("dy", 0)
        .attr("x", function(d) {
          return d.children || d._children ? -13 : 13;
        })
        .attr("text-anchor", function(d) {
          return d.children || d._children ? "end" : "start";
        })
        .text(function(d) {
          return d.data.name;
        });
*/
      var diameter = 50;
      nodeEnter
        .append("image")
        .on("click", click)
        .attr("xlink:href", function(d) {
          return d.data.img;
        })
        .attr("height", diameter * 2)
        .attr("transform", "translate(-50," + -50 + ")");

      // UPDATE
      var nodeUpdate = nodeEnter.merge(node);

      // Transition to the proper position for the node
      nodeUpdate
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + d.y + "," + d.x + ")";
        });

      // Update the node attributes and style
      nodeUpdate
        .select("circle.node")
        .attr("r", diameter)

        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        })
        .attr("cursor", "pointer");

      nodeUpdate
        .append("circle")
        .on("click", click2)
        .attr("additional", "extra_circle")
        .attr("r", 20)
        .attr("transform", "translate(0," + -65 + ")");
      // Remove any exiting nodes
      var nodeExit = node
        .exit()
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + source.y + "," + source.x + ")";
        })
        .remove();

      // On exit reduce the node circles size to 0
      nodeExit.select("circle").attr("r", 1e-6);

      // On exit reduce the opacity of text labels
      nodeExit.select("text").style("fill-opacity", 1e-6);

      // ****************** links section ***************************

      // Update the links...
      var link = svg.selectAll("path.link").data(links, function(d) {
        return d.id;
      });

      // Enter any new links at the parent's previous position.
      var linkEnter = link
        .enter()
        .insert("path", "g")
        .attr("class", "link")
        .attr("d", function(d) {
          var o = { x: source.x0, y: source.y0 };
          return diagonal(o, o);
        });

      // UPDATE
      var linkUpdate = linkEnter.merge(link);

      // Transition back to the parent element position
      linkUpdate
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          return diagonal(d, d.parent);
        });

      // Remove any exiting links
      var linkExit = link
        .exit()
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          var o = { x: source.x, y: source.y };
          return diagonal(o, o);
        })
        .remove();

      // Store the old positions for transition.
      nodes.forEach(function(d) {
        d.x0 = d.x;
        d.y0 = d.y;
      });

      // Creates a curved (diagonal) path from parent to the child nodes
      function diagonal(s, d) {
        var path = `M ${s.y} ${s.x}
            C ${(s.y + d.y) / 2} ${s.x},
              ${(s.y + d.y) / 2} ${d.x},
              ${d.y} ${d.x}`;

        return path;
      }

      // Toggle children on click.
      function click(d) {
        if (d.children) {
          d._children = d.children;
          d.children = null;
        } else {
          d.children = d._children;
          d._children = null;
        }
        update(d);
      }
      function click2(d) {
        this.setState({ collapse: !this.state.collapse });

        alert("You clicked on more!" + d.data.name);
      }
    }
  }

  updateWindowDimensions() {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  }



  render() {
    return (
      <div>
        <Button
          color="primary"

          style={{ marginBottom: "1rem" }}
        >
          Toggle
        </Button>
        <Collapse isOpen={this.state.collapse}>
          <Card>
            <CardBody>
              Anim pariatur cliche reprehenderit, enim eiusmod high life
              accusamus terry richardson ad squid. Nihil anim keffiyeh
              helvetica, craft beer labore wes anderson cred nesciunt sapiente
              ea proident.
            </CardBody>
          </Card>
        </Collapse>
      </div>
    );
      }
    }

    export default Tree;

Sorry if that's a lot of code, I deleted my var treeData which is a json object 100 lines long

I am using some d3 for visualization and decided to also use reactstrap. Basically clicking a circle in d3 will result in the reactstrap element Collapse to appear.

I am not finding any luck with setState... I am doing all my react code in ponenetDidMount(), inside of ponentDidMount(), I have a function update(), and in update, I have a function called click, and when click triggers, it does:

this.setState({ collapse: !this.state.collapse });

It doesn't work, and I lack the fundamental JS to reason why, I am assuming that the this keyword is referring to the function update instead of my ponent "Tree"?

Code:

import React, { Component } from "react";
import * as d3 from "d3";
import { hierarchy, tree } from "d3-hierarchy";

import { Collapse, Button, CardBody, Card } from "reactstrap";

class Tree extends Component {
  constructor(props) {
    super(props);
    this.state = { collapse: false };
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
    //this.toggle = this.toggle.bind(this);
  }

  ponentDidMount() {
    this.updateWindowDimensions();


    // Set the dimensions and margins of the diagram
    var height1 = window.innerHeight;
    var margin = { top: 10, right: 90, bottom: 30, left: 180 },
      width = 1080 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    // appends a 'group' element to 'svg'
    // moves the 'group' element to the top left margin
    var svg = d3
      .select("body")
      .append("svg")
      .attr("width", window.innerWidth - margin.right - margin.left)
      .attr("height", window.innerHeight - margin.top - margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var i = 0,
      duration = 500,
      root;

    // declares a tree layout and assigns the size
    var treemap = d3.tree().size([window.innerHeight, window.innerWidth]);

    root = d3.hierarchy(treeData, function(d) {
      return d.children;
    });
    root.x0 = height / 2;
    root.y0 = 0;

    // Collapse after the second level
    root.children.forEach(collapse);

    update(root);

    // Collapse the node and all it's children
    function collapse(d) {
      if (d.children) {
        d._children = d.children;
        d._children.forEach(collapse);
        d.children = null;
      }
    }

    function update(source) {
      // Assigns the x and y position for the nodes

      var treeData = treemap(root);

      // Compute the new tree layout.
      var nodes = treeData.descendants(),
        links = treeData.descendants().slice(1),
        more_button = treeData.descendants();

      // Normalize for fixed-depth.
      nodes.forEach(function(d) {
        d.y = d.depth * 360;
      });

      // ****************** Nodes section ***************************

      // Update the nodes...
      var node = svg.selectAll("g.node").data(nodes, function(d) {
        return d.id || (d.id = ++i);
      });

      // Enter any new modes at the parent's previous position.
      var nodeEnter = node
        .enter()
        .append("g")
        .attr("class", "node")

        //if deleted, bubbles e from the very top, is weird
        .attr("transform", function(d) {
          return "translate(" + source.y0 + "," + source.x0 + ")";
        });

      // Add Circle for the nodes
      nodeEnter
        .append("circle")
        .attr("class", "node")
        .attr("r", 1e-6)
        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        });

      /*
// Add labels for the nodes
      nodeEnter
        .append("text")
        .attr("dy", 0)
        .attr("x", function(d) {
          return d.children || d._children ? -13 : 13;
        })
        .attr("text-anchor", function(d) {
          return d.children || d._children ? "end" : "start";
        })
        .text(function(d) {
          return d.data.name;
        });
*/
      var diameter = 50;
      nodeEnter
        .append("image")
        .on("click", click)
        .attr("xlink:href", function(d) {
          return d.data.img;
        })
        .attr("height", diameter * 2)
        .attr("transform", "translate(-50," + -50 + ")");

      // UPDATE
      var nodeUpdate = nodeEnter.merge(node);

      // Transition to the proper position for the node
      nodeUpdate
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + d.y + "," + d.x + ")";
        });

      // Update the node attributes and style
      nodeUpdate
        .select("circle.node")
        .attr("r", diameter)

        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        })
        .attr("cursor", "pointer");

      nodeUpdate
        .append("circle")
        .on("click", click2)
        .attr("additional", "extra_circle")
        .attr("r", 20)
        .attr("transform", "translate(0," + -65 + ")");
      // Remove any exiting nodes
      var nodeExit = node
        .exit()
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + source.y + "," + source.x + ")";
        })
        .remove();

      // On exit reduce the node circles size to 0
      nodeExit.select("circle").attr("r", 1e-6);

      // On exit reduce the opacity of text labels
      nodeExit.select("text").style("fill-opacity", 1e-6);

      // ****************** links section ***************************

      // Update the links...
      var link = svg.selectAll("path.link").data(links, function(d) {
        return d.id;
      });

      // Enter any new links at the parent's previous position.
      var linkEnter = link
        .enter()
        .insert("path", "g")
        .attr("class", "link")
        .attr("d", function(d) {
          var o = { x: source.x0, y: source.y0 };
          return diagonal(o, o);
        });

      // UPDATE
      var linkUpdate = linkEnter.merge(link);

      // Transition back to the parent element position
      linkUpdate
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          return diagonal(d, d.parent);
        });

      // Remove any exiting links
      var linkExit = link
        .exit()
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          var o = { x: source.x, y: source.y };
          return diagonal(o, o);
        })
        .remove();

      // Store the old positions for transition.
      nodes.forEach(function(d) {
        d.x0 = d.x;
        d.y0 = d.y;
      });

      // Creates a curved (diagonal) path from parent to the child nodes
      function diagonal(s, d) {
        var path = `M ${s.y} ${s.x}
            C ${(s.y + d.y) / 2} ${s.x},
              ${(s.y + d.y) / 2} ${d.x},
              ${d.y} ${d.x}`;

        return path;
      }

      // Toggle children on click.
      function click(d) {
        if (d.children) {
          d._children = d.children;
          d.children = null;
        } else {
          d.children = d._children;
          d._children = null;
        }
        update(d);
      }
      function click2(d) {
        this.setState({ collapse: !this.state.collapse });

        alert("You clicked on more!" + d.data.name);
      }
    }
  }

  updateWindowDimensions() {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  }



  render() {
    return (
      <div>
        <Button
          color="primary"

          style={{ marginBottom: "1rem" }}
        >
          Toggle
        </Button>
        <Collapse isOpen={this.state.collapse}>
          <Card>
            <CardBody>
              Anim pariatur cliche reprehenderit, enim eiusmod high life
              accusamus terry richardson ad squid. Nihil anim keffiyeh
              helvetica, craft beer labore wes anderson cred nesciunt sapiente
              ea proident.
            </CardBody>
          </Card>
        </Collapse>
      </div>
    );
      }
    }

    export default Tree;

Sorry if that's a lot of code, I deleted my var treeData which is a json object 100 lines long

Share Improve this question edited Jan 24, 2019 at 0:13 Acy asked Jan 24, 2019 at 0:07 AcyAcy 6592 gold badges11 silver badges29 bronze badges 3
  • Better show more code – SAP Commented Jan 24, 2019 at 0:09
  • That's my bad, posted now – Acy Commented Jan 24, 2019 at 0:13
  • 1 First thing it doesn’t make sense to declare functions inside ponentDidMount they should be defined outside ponentDidMount and call them inside the method. Second, perhaps, The reason your setState is not working May be you are using regular functions without manual binding or change those functions to arrow functions to resolve the issue. As @SAP mentioned please share relevant code for better reception here – Hemadri Dasari Commented Jan 24, 2019 at 0:16
Add a ment  | 

1 Answer 1

Reset to default 5

You won’t get this context inside the regular function unless you bind this to the function or change it to arrow function

So, Change

  function click2(d) {
    this.setState({ collapse: !this.state.collapse });

    alert("You clicked on more!" + d.data.name);
  }

To

  const click2 = d => {
    this.setState({ collapse: !this.state.collapse });

    alert("You clicked on more!" + d.data.name);
  }

Or bind it manually

   function click2(d) {
    this.setState({ collapse: !this.state.collapse });

    alert("You clicked on more!" + d.data.name);
  }.bind(this)

Or move the function outside ponentDidMount and do manual binding in constructor as

    this.click2 = this.click2.bind(this);

I am using some d3 for visualization and decided to also use reactstrap. Basically clicking a circle in d3 will result in the reactstrap element Collapse to appear.

I am not finding any luck with setState... I am doing all my react code in ponenetDidMount(), inside of ponentDidMount(), I have a function update(), and in update, I have a function called click, and when click triggers, it does:

this.setState({ collapse: !this.state.collapse });

It doesn't work, and I lack the fundamental JS to reason why, I am assuming that the this keyword is referring to the function update instead of my ponent "Tree"?

Code:

import React, { Component } from "react";
import * as d3 from "d3";
import { hierarchy, tree } from "d3-hierarchy";

import { Collapse, Button, CardBody, Card } from "reactstrap";

class Tree extends Component {
  constructor(props) {
    super(props);
    this.state = { collapse: false };
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
    //this.toggle = this.toggle.bind(this);
  }

  ponentDidMount() {
    this.updateWindowDimensions();


    // Set the dimensions and margins of the diagram
    var height1 = window.innerHeight;
    var margin = { top: 10, right: 90, bottom: 30, left: 180 },
      width = 1080 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    // appends a 'group' element to 'svg'
    // moves the 'group' element to the top left margin
    var svg = d3
      .select("body")
      .append("svg")
      .attr("width", window.innerWidth - margin.right - margin.left)
      .attr("height", window.innerHeight - margin.top - margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var i = 0,
      duration = 500,
      root;

    // declares a tree layout and assigns the size
    var treemap = d3.tree().size([window.innerHeight, window.innerWidth]);

    root = d3.hierarchy(treeData, function(d) {
      return d.children;
    });
    root.x0 = height / 2;
    root.y0 = 0;

    // Collapse after the second level
    root.children.forEach(collapse);

    update(root);

    // Collapse the node and all it's children
    function collapse(d) {
      if (d.children) {
        d._children = d.children;
        d._children.forEach(collapse);
        d.children = null;
      }
    }

    function update(source) {
      // Assigns the x and y position for the nodes

      var treeData = treemap(root);

      // Compute the new tree layout.
      var nodes = treeData.descendants(),
        links = treeData.descendants().slice(1),
        more_button = treeData.descendants();

      // Normalize for fixed-depth.
      nodes.forEach(function(d) {
        d.y = d.depth * 360;
      });

      // ****************** Nodes section ***************************

      // Update the nodes...
      var node = svg.selectAll("g.node").data(nodes, function(d) {
        return d.id || (d.id = ++i);
      });

      // Enter any new modes at the parent's previous position.
      var nodeEnter = node
        .enter()
        .append("g")
        .attr("class", "node")

        //if deleted, bubbles e from the very top, is weird
        .attr("transform", function(d) {
          return "translate(" + source.y0 + "," + source.x0 + ")";
        });

      // Add Circle for the nodes
      nodeEnter
        .append("circle")
        .attr("class", "node")
        .attr("r", 1e-6)
        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        });

      /*
// Add labels for the nodes
      nodeEnter
        .append("text")
        .attr("dy", 0)
        .attr("x", function(d) {
          return d.children || d._children ? -13 : 13;
        })
        .attr("text-anchor", function(d) {
          return d.children || d._children ? "end" : "start";
        })
        .text(function(d) {
          return d.data.name;
        });
*/
      var diameter = 50;
      nodeEnter
        .append("image")
        .on("click", click)
        .attr("xlink:href", function(d) {
          return d.data.img;
        })
        .attr("height", diameter * 2)
        .attr("transform", "translate(-50," + -50 + ")");

      // UPDATE
      var nodeUpdate = nodeEnter.merge(node);

      // Transition to the proper position for the node
      nodeUpdate
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + d.y + "," + d.x + ")";
        });

      // Update the node attributes and style
      nodeUpdate
        .select("circle.node")
        .attr("r", diameter)

        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        })
        .attr("cursor", "pointer");

      nodeUpdate
        .append("circle")
        .on("click", click2)
        .attr("additional", "extra_circle")
        .attr("r", 20)
        .attr("transform", "translate(0," + -65 + ")");
      // Remove any exiting nodes
      var nodeExit = node
        .exit()
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + source.y + "," + source.x + ")";
        })
        .remove();

      // On exit reduce the node circles size to 0
      nodeExit.select("circle").attr("r", 1e-6);

      // On exit reduce the opacity of text labels
      nodeExit.select("text").style("fill-opacity", 1e-6);

      // ****************** links section ***************************

      // Update the links...
      var link = svg.selectAll("path.link").data(links, function(d) {
        return d.id;
      });

      // Enter any new links at the parent's previous position.
      var linkEnter = link
        .enter()
        .insert("path", "g")
        .attr("class", "link")
        .attr("d", function(d) {
          var o = { x: source.x0, y: source.y0 };
          return diagonal(o, o);
        });

      // UPDATE
      var linkUpdate = linkEnter.merge(link);

      // Transition back to the parent element position
      linkUpdate
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          return diagonal(d, d.parent);
        });

      // Remove any exiting links
      var linkExit = link
        .exit()
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          var o = { x: source.x, y: source.y };
          return diagonal(o, o);
        })
        .remove();

      // Store the old positions for transition.
      nodes.forEach(function(d) {
        d.x0 = d.x;
        d.y0 = d.y;
      });

      // Creates a curved (diagonal) path from parent to the child nodes
      function diagonal(s, d) {
        var path = `M ${s.y} ${s.x}
            C ${(s.y + d.y) / 2} ${s.x},
              ${(s.y + d.y) / 2} ${d.x},
              ${d.y} ${d.x}`;

        return path;
      }

      // Toggle children on click.
      function click(d) {
        if (d.children) {
          d._children = d.children;
          d.children = null;
        } else {
          d.children = d._children;
          d._children = null;
        }
        update(d);
      }
      function click2(d) {
        this.setState({ collapse: !this.state.collapse });

        alert("You clicked on more!" + d.data.name);
      }
    }
  }

  updateWindowDimensions() {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  }



  render() {
    return (
      <div>
        <Button
          color="primary"

          style={{ marginBottom: "1rem" }}
        >
          Toggle
        </Button>
        <Collapse isOpen={this.state.collapse}>
          <Card>
            <CardBody>
              Anim pariatur cliche reprehenderit, enim eiusmod high life
              accusamus terry richardson ad squid. Nihil anim keffiyeh
              helvetica, craft beer labore wes anderson cred nesciunt sapiente
              ea proident.
            </CardBody>
          </Card>
        </Collapse>
      </div>
    );
      }
    }

    export default Tree;

Sorry if that's a lot of code, I deleted my var treeData which is a json object 100 lines long

I am using some d3 for visualization and decided to also use reactstrap. Basically clicking a circle in d3 will result in the reactstrap element Collapse to appear.

I am not finding any luck with setState... I am doing all my react code in ponenetDidMount(), inside of ponentDidMount(), I have a function update(), and in update, I have a function called click, and when click triggers, it does:

this.setState({ collapse: !this.state.collapse });

It doesn't work, and I lack the fundamental JS to reason why, I am assuming that the this keyword is referring to the function update instead of my ponent "Tree"?

Code:

import React, { Component } from "react";
import * as d3 from "d3";
import { hierarchy, tree } from "d3-hierarchy";

import { Collapse, Button, CardBody, Card } from "reactstrap";

class Tree extends Component {
  constructor(props) {
    super(props);
    this.state = { collapse: false };
    this.updateWindowDimensions = this.updateWindowDimensions.bind(this);
    //this.toggle = this.toggle.bind(this);
  }

  ponentDidMount() {
    this.updateWindowDimensions();


    // Set the dimensions and margins of the diagram
    var height1 = window.innerHeight;
    var margin = { top: 10, right: 90, bottom: 30, left: 180 },
      width = 1080 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    // append the svg object to the body of the page
    // appends a 'group' element to 'svg'
    // moves the 'group' element to the top left margin
    var svg = d3
      .select("body")
      .append("svg")
      .attr("width", window.innerWidth - margin.right - margin.left)
      .attr("height", window.innerHeight - margin.top - margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var i = 0,
      duration = 500,
      root;

    // declares a tree layout and assigns the size
    var treemap = d3.tree().size([window.innerHeight, window.innerWidth]);

    root = d3.hierarchy(treeData, function(d) {
      return d.children;
    });
    root.x0 = height / 2;
    root.y0 = 0;

    // Collapse after the second level
    root.children.forEach(collapse);

    update(root);

    // Collapse the node and all it's children
    function collapse(d) {
      if (d.children) {
        d._children = d.children;
        d._children.forEach(collapse);
        d.children = null;
      }
    }

    function update(source) {
      // Assigns the x and y position for the nodes

      var treeData = treemap(root);

      // Compute the new tree layout.
      var nodes = treeData.descendants(),
        links = treeData.descendants().slice(1),
        more_button = treeData.descendants();

      // Normalize for fixed-depth.
      nodes.forEach(function(d) {
        d.y = d.depth * 360;
      });

      // ****************** Nodes section ***************************

      // Update the nodes...
      var node = svg.selectAll("g.node").data(nodes, function(d) {
        return d.id || (d.id = ++i);
      });

      // Enter any new modes at the parent's previous position.
      var nodeEnter = node
        .enter()
        .append("g")
        .attr("class", "node")

        //if deleted, bubbles e from the very top, is weird
        .attr("transform", function(d) {
          return "translate(" + source.y0 + "," + source.x0 + ")";
        });

      // Add Circle for the nodes
      nodeEnter
        .append("circle")
        .attr("class", "node")
        .attr("r", 1e-6)
        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        });

      /*
// Add labels for the nodes
      nodeEnter
        .append("text")
        .attr("dy", 0)
        .attr("x", function(d) {
          return d.children || d._children ? -13 : 13;
        })
        .attr("text-anchor", function(d) {
          return d.children || d._children ? "end" : "start";
        })
        .text(function(d) {
          return d.data.name;
        });
*/
      var diameter = 50;
      nodeEnter
        .append("image")
        .on("click", click)
        .attr("xlink:href", function(d) {
          return d.data.img;
        })
        .attr("height", diameter * 2)
        .attr("transform", "translate(-50," + -50 + ")");

      // UPDATE
      var nodeUpdate = nodeEnter.merge(node);

      // Transition to the proper position for the node
      nodeUpdate
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + d.y + "," + d.x + ")";
        });

      // Update the node attributes and style
      nodeUpdate
        .select("circle.node")
        .attr("r", diameter)

        .style("fill", function(d) {
          return d._children ? "lightsteelblue" : "#fff";
        })
        .attr("cursor", "pointer");

      nodeUpdate
        .append("circle")
        .on("click", click2)
        .attr("additional", "extra_circle")
        .attr("r", 20)
        .attr("transform", "translate(0," + -65 + ")");
      // Remove any exiting nodes
      var nodeExit = node
        .exit()
        .transition()
        .duration(duration)
        .attr("transform", function(d) {
          return "translate(" + source.y + "," + source.x + ")";
        })
        .remove();

      // On exit reduce the node circles size to 0
      nodeExit.select("circle").attr("r", 1e-6);

      // On exit reduce the opacity of text labels
      nodeExit.select("text").style("fill-opacity", 1e-6);

      // ****************** links section ***************************

      // Update the links...
      var link = svg.selectAll("path.link").data(links, function(d) {
        return d.id;
      });

      // Enter any new links at the parent's previous position.
      var linkEnter = link
        .enter()
        .insert("path", "g")
        .attr("class", "link")
        .attr("d", function(d) {
          var o = { x: source.x0, y: source.y0 };
          return diagonal(o, o);
        });

      // UPDATE
      var linkUpdate = linkEnter.merge(link);

      // Transition back to the parent element position
      linkUpdate
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          return diagonal(d, d.parent);
        });

      // Remove any exiting links
      var linkExit = link
        .exit()
        .transition()
        .duration(duration)
        .attr("d", function(d) {
          var o = { x: source.x, y: source.y };
          return diagonal(o, o);
        })
        .remove();

      // Store the old positions for transition.
      nodes.forEach(function(d) {
        d.x0 = d.x;
        d.y0 = d.y;
      });

      // Creates a curved (diagonal) path from parent to the child nodes
      function diagonal(s, d) {
        var path = `M ${s.y} ${s.x}
            C ${(s.y + d.y) / 2} ${s.x},
              ${(s.y + d.y) / 2} ${d.x},
              ${d.y} ${d.x}`;

        return path;
      }

      // Toggle children on click.
      function click(d) {
        if (d.children) {
          d._children = d.children;
          d.children = null;
        } else {
          d.children = d._children;
          d._children = null;
        }
        update(d);
      }
      function click2(d) {
        this.setState({ collapse: !this.state.collapse });

        alert("You clicked on more!" + d.data.name);
      }
    }
  }

  updateWindowDimensions() {
    this.setState({ width: window.innerWidth, height: window.innerHeight });
  }



  render() {
    return (
      <div>
        <Button
          color="primary"

          style={{ marginBottom: "1rem" }}
        >
          Toggle
        </Button>
        <Collapse isOpen={this.state.collapse}>
          <Card>
            <CardBody>
              Anim pariatur cliche reprehenderit, enim eiusmod high life
              accusamus terry richardson ad squid. Nihil anim keffiyeh
              helvetica, craft beer labore wes anderson cred nesciunt sapiente
              ea proident.
            </CardBody>
          </Card>
        </Collapse>
      </div>
    );
      }
    }

    export default Tree;

Sorry if that's a lot of code, I deleted my var treeData which is a json object 100 lines long

Share Improve this question edited Jan 24, 2019 at 0:13 Acy asked Jan 24, 2019 at 0:07 AcyAcy 6592 gold badges11 silver badges29 bronze badges 3
  • Better show more code – SAP Commented Jan 24, 2019 at 0:09
  • That's my bad, posted now – Acy Commented Jan 24, 2019 at 0:13
  • 1 First thing it doesn’t make sense to declare functions inside ponentDidMount they should be defined outside ponentDidMount and call them inside the method. Second, perhaps, The reason your setState is not working May be you are using regular functions without manual binding or change those functions to arrow functions to resolve the issue. As @SAP mentioned please share relevant code for better reception here – Hemadri Dasari Commented Jan 24, 2019 at 0:16
Add a ment  | 

1 Answer 1

Reset to default 5

You won’t get this context inside the regular function unless you bind this to the function or change it to arrow function

So, Change

  function click2(d) {
    this.setState({ collapse: !this.state.collapse });

    alert("You clicked on more!" + d.data.name);
  }

To

  const click2 = d => {
    this.setState({ collapse: !this.state.collapse });

    alert("You clicked on more!" + d.data.name);
  }

Or bind it manually

   function click2(d) {
    this.setState({ collapse: !this.state.collapse });

    alert("You clicked on more!" + d.data.name);
  }.bind(this)

Or move the function outside ponentDidMount and do manual binding in constructor as

    this.click2 = this.click2.bind(this);

本文标签: javascriptReact Setting state inside of a functionStack Overflow