function update(source) {
  treemap = d3.tree()
    .nodeSize([hSlider * 5, hSlider * 5]);

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

  // Toggle children on click.
  const click = (d) => {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    d3.selectAll('text').attr('class', 'text');
    update(d);
  };

  // Assigns the x and y position for the nodes
  let treeData = treemap(root);

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

  // Normalize for fixed-depth.
  nodes.forEach((d) => { d.y = d.depth * vSlider * 10; });

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

  // Update the nodes...
  let node = svg.selectAll('g.node')
    .data(nodes, (d) => {
      if (d.data.id === selectedNode) {
        updateStateProps(d.data.state, d.data.props);
      }
      return d.data.id;
    });

  // Remove any exiting nodes
  let nodeExit = node.exit().transition()
    .duration(duration)
    .attr('transform', () => `translate(${source.x},${source.y})`)
    // .attr('transform', d => 'translate(' + source.x + ',' + source.y + ')')
    .remove();

  let nodeEnter = node.enter().append('g')
    .attr('class', 'node')
    .attr('transform', () => `translate(${source.x0},${source.y0})`)
    .on('click', click);

  // Add Circle for the nodes
  nodeEnter.append('circle')
    .attr('class', 'node')
    .attr('r', 5)
    .style('fill', d => d._children ? 'lightsteelblue' : '#fff')
    .style('pointer-events', 'visible')

    .on('mouseover', function (d) {
      d3.selectAll('circle')
        .style('stroke-width', 1)
        .style('stroke', 'black');
      d3.select(this)
        .style('stroke-width', 5)
        .style('stroke', '#754abb');
      selectedNode = d.data.id;
      updateStateProps(d.data.state, d.data.props);

      const breadcrumb = document.querySelector('.breadcrumb');
      const items = breadcrumb.getElementsByTagName('*');
      for (let i = 0; i < items.length; i++) {
        const html = items[i].innerHTML;

        if (html === d.data.name) {
          items[i].style.color = '#B30089';
        }
        else if (html.slice(0, html.indexOf('[')) == d.data.name) {
          items[i].style.color = '#B30089';
        }
        else {
          items[i].style.color = '#0275d8';
        }
      }
    });
  // Add labels for the nodes
  nodeEnter.append('text')
    .attr('dy', '.35em')
    .attr('y', d => d.children || d._children ? -24 : 24)
    .attr('text-anchor', 'middle')
    .text(d => d.data.name);

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

  // Transition to the proper position for the node
  nodeUpdate.transition()
    .duration(duration)
    .attr('transform', d => `translate(${d.x},${d.y})`);

  // Update the node attributes and style
  nodeUpdate.select('circle.node')
    .attr('r', 10)
    .style('fill', d => d._children ? 'lightsteelblue' : '#fff')
    .attr('cursor', 'pointer');    // 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...
  let link = svg.selectAll('path.link')
    .data(links, d => d.data.id);

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

  // Transition back to the parent element position
  linkUpdate.transition()
    .duration(duration)
    .attr('d', d => diagonal(d, d.parent));

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

  // Store the old positions for transition.
  nodes.forEach(d => {
    d.x0 = d.x;
    d.y0 = d.y;
  });
}
Update the tree with new data

@param {object} source - parsed representation of React's vDOM