React useEffect загружает новое, но не очищает старое

#reactjs #mobx #use-effect

#reactjs #mobx #use-effect

Вопрос:

https://codesandbox.io/s/stacked-bar-useeffect-upbf8

В приведенном выше коде ключ props изменяется, а график обновляется, но предыдущая итерация все еще отображается и создает беспорядок. Где я ошибаюсь? Я попытался выполнить очистку и использовал минимальный код, необходимый для просмотра того, что я могу обновить, но я все равно получаю тот же результат.

       <Observer>
        {() => <BarStacked keys={store.keys} store={store} />}
      </Observer>
 
 
    const BarStacked = (props) => {
  var max_y = 100;

  const margin = props.store.graphPreferences.margin;
  const width = props.store.graphPreferences.width;
  const height = props.store.graphPreferences.height;
  const svgRefHours = useRef();

  useEffect(() => {
    const svg = d3.select(svgRefHours.current);

    const chart = svg
      .append("g")
      .attr("transform", `translate(${margin}, ${margin})`);

    const stackGenerator = stack()
      .keys(props.store.keys)
      .order(stackOrderAscending);
    const layers = stackGenerator(data);
    const extent = [
      0,
      max(layers, (layer) => max(layer, (sequency) => sequency[1]))
    ];

    const xScale = d3
      .scaleBand()
      .domain(data.map((d) => d.dayofmonth))
      .range([0, width])
      .padding(0.25);

    const xAxis = axisBottom(xScale);

    const yScale = d3.scaleLinear().domain(extent).range([height, 0]);

    // vertical grid lines
    const makeXLines = () => d3.axisBottom().scale(xScale);

    const makeYLines = () => d3.axisLeft().scale(yScale);

    chart
      .append("g")
      .attr("transform", `translate(0, ${height})`)
      .call(d3.axisBottom(xScale));

    chart.append("g").call(d3.axisLeft(yScale));

    // vertical grid lines
    chart
      .append("g")
      .attr("class", "grid")
      .attr("transform", `translate(0, ${height})`)
      .call(makeXLines().tickSize(-height, 0, 0).tickFormat(""));

    chart
      .append("g")
      .attr("class", "grid")
      .call(makeYLines().tickSize(-width, 0, 0).tickFormat(""));

    const barGroups = chart.selectAll().data(data).enter().append("g");

    barGroups
      .selectAll(".layer")
      .data(layers)
      .join("g")
      .attr("class", "layer")
      .attr("fill", (layer) => props.store.colors[layer.key])
      .selectAll("rect")
      .data((layer) => layer)
      .join("rect")
      .attr("x", (sequence) => xScale(sequence.data.dayofmonth))
      .attr("width", xScale.bandwidth())
      .attr("y", (sequence) => yScale(sequence[1]))
      .attr("height", (sequence) => yScale(sequence[0]) - yScale(sequence[1]))
      .on("mouseover", function () {
        //  d3.selectAll(".dayofmonth").attr("fill", )
        d3.select(this).attr("fill", "blue");
      })
      .on("mouseout", function () {
        d3.select(this).attr("fill", (layer) => props.store.colors[layer.key]);
      });

    const yAxis = axisLeft(yScale);
    svg.select(".y-axis").call(yAxis);

    svg
      .append("text")
      .attr("class", "label")
      .attr("x", -(height / 2) - margin)
      .attr("y", margin / 2.4)
      .attr("transform", "rotate(-90)")
      .attr("text-anchor", "middle")
      .text("Number of Tracks");

    svg
      .append("text")
      .attr("class", "label")
      .attr("x", width / 2   margin)
      .attr("y", height   margin * 1.7)
      .attr("text-anchor", "middle")
      .text("Day of the Month");

    svg
      .append("text")
      .attr("class", "title")
      .attr("x", width / 2   margin)
      .attr("y", 40)
      .attr("text-anchor", "middle")
      .text("Tracks per day of the month");

    return () => {};
  }, [
    height,
    max_y,
    props,
    width,
    margin,
    props.store.colors,
    props.store.keys
  ]);

  return (
    <svg ref={svgRefHours}>
      <g className="x-axis" />
      <g className="y-axis" />
    </svg>
  );
};

 

** редактирование заключалось в добавлении кода, ссылка по-прежнему доступна для получения дополнительной информации, поскольку я не был уверен, что имеет отношение к вопросу.

Комментарии:

1. Должно ли быть возможно просматривать только один датчик одновременно? Похоже, вам нужно очистить SVG, прежде чем пытаться снова отобразить его.

2. svg-код в порядке, при первоначальном рендеринге он работает нормально. Если я настрою ключ вручную, он загружается так, как должен. Предыдущий рендеринг просто не исчезает.