title: How to update d3-force elements?
body: <p>I want to update <code>d3-force</code> elements when click, but I find something wrong.
  What I want is:</p>
  <ol>
  <li>generate all links first</li>
  <li>then generate all nodes, so that the node can override the link</li>
  </ol>
  <p>So when clicked the elements should be:</p>
  <pre><code>&lt;svg&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
  &lt;/svg&gt;
  </code></pre>
  <p>But I get:</p>
  <pre><code>&lt;svg&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;line ...&gt;&lt;/line&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
    &lt;g&gt;&lt;circle ...&gt;&lt;/circle&gt;&lt;/g&gt;
  &lt;/svg&gt;
  </code></pre>
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>const width = 800;
  const height = 400;
  
  const svg = d3.select("svg").attr("viewBox", [0, 0, width, height]);
  let node = svg.selectAll(".node");
  let link = svg.selectAll(".link");
  
  const simulation = d3
    .forceSimulation()
    .force("center", d3.forceCenter(width / 2, height / 2))
    .on("tick", (d) =&gt; {
      link
        .attr("x1", d =&gt; d.source.x)
        .attr("y1", d =&gt; d.source.y)
        .attr("x2", d =&gt; d.target.x)
        .attr("y2", d =&gt; d.target.y);
  
      node
        .attr("transform", d =&gt; `translate(${d.x}, ${d.y})`);
    });
  
  const root = {
    x: width / 2,
    y: height / 2,
    level: 0,
    id: "1"
  };
  
  function genChildren(p) {
    const dist = 100 / (p.level + 1);
    const nodes = [{
        x: p.x - dist,
        y: p.y,
        level: p.level + 1,
        id: p.id + "1"
      },
      {
        x: p.x + dist,
        y: p.y,
        level: p.level + 1,
        id: p.id + "2"
      },
      {
        x: p.x,
        y: p.y - dist,
        level: p.level + 1,
        id: p.id + "3"
      },
      {
        x: p.x,
        y: p.y + dist,
        level: p.level + 1,
        id: p.id + "4"
      },
    ];
    const links = nodes.map(v =&gt; ({
      source: p.id,
      target: v.id
    }));
    return {
      nodes,
      links
    };
  }
  
  
  function update(nodes, links) {
    link = link.data(links)
      .join(enter =&gt; {
        return enter.append("line")
          .attr("stroke", "#000")
          .attr("stroke-width", "1.5px")
          .call(enter =&gt; enter.transition().attr("stroke-opacity", 1));
      }, update =&gt; update, exit =&gt; exit.remove());
    node = node.data(nodes, d =&gt; d.id)
      .join(
        enter =&gt; {
          const g = enter.append("g");
          g.append("circle")
            .attr("r", 12)
            .attr("cursor", "move")
            .attr("fill", "#ccc")
            .attr("stroke", "#000")
            .attr("stroke-width", "1.5px");
          return g;
        },
        update =&gt; update,
        exit =&gt; exit.remove(),
      )
      .attr("transform", function(d) {
        return "translate(" + d.x + ", " + d.y + ")";
      })
      .on("click", (ev, d) =&gt; {
        if (d.level !== 0) {
          return;
        }
        const childrenInfo = genChildren(root)
        const nodes = d.active ? [root] : [root].concat(childrenInfo.nodes);
        const links = d.active ? [] : childrenInfo.links;
        d.active = !d.active;
        update(nodes, links);
      });
  
    simulation.nodes(nodes).force("link", d3.forceLink(links).id(node =&gt; node.id).strength(-0.01));
  
    if (simulation.alpha() &lt;= 1) {
      simulation.alpha(1);
      simulation.restart();
    }
  }
  
  update([root], [])</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"&gt;&lt;/script&gt;
  &lt;svg&gt;&lt;/svg&gt;</code></pre>
  </div>
  </div>
  </p>