Missing data after adding the time range

Viewed 61

I've been struggling for hours, but I can't figure out what I'm doing wrong. Namely, my goal is to show a line graph with the number of infected people in a certain unit of time, where the y axis would show the number of infected and the x axis the time range. This is what the graph should look like:

Line Graph

However, after adding the time range to the x-axis, the line related to the number of infected people in a unit of time is no longer displayed This is what the graph look like:

Line Graph

The path for svg seems to be made:

Chrome Dev Tools

I appreciate any help..

import React, { useEffect, useRef } from "react";
import { useSelector } from "react-redux";
import {
  select,
  line,
  curveCardinal,
  scaleLinear,
  max,
  scaleTime,
  axisBottom,
  axisLeft,
  extent,
} from "d3";

const ChartFirstCase = () => {
  const fromFirstDayData = useSelector((state) => state.fromFirstDayData);
  const { allData } = fromFirstDayData;

  const cases = allData ? allData.map((data) => data.Cases) : [];
  const dates = allData ? allData.map((data) => data.Dates) : [];

  const getDate = (dateValue) => {
    const date = dateValue;
    return new Date(date);
  };

  const days = extent(dates);
  const minDate = getDate(days[0]);
  const maxDate = getDate(days[1]);

  const sorting = (a, b) => a - b;
  cases.sort(sorting);

  const svgRef = useRef();
  const svgHeight = 200;
  const svgWidth = 400;

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

    const maxProp = allData
      ? max(allData.map((broj) => broj.Cases))
      : "";

    const xScale = scaleTime().domain([minDate, maxDate]).range([0, 400]);
    const yScale = scaleLinear()
      .domain([0, maxProp + 50000])
      .range([200, 0]);

    const xAxis = axisBottom(xScale).ticks(5);
    const yAxis = axisLeft(yScale).ticks(5);

    svg.select(".x-axis").style("transform", "translateY(200px)").call(xAxis);
    svg.select(".y-axis").call(yAxis);

    const casesLine = line()
      .x((value, index) => xScale(index))
      .y(yScale)
      .curve(curveCardinal);

    svg
      .selectAll(".line")
      .data([cases])
      .join("path")
      .attr("class", "line")
      .attr("d", casesLine)
      .attr("fill", "none")
      .attr("stroke", "red");
  }, [cases, allData, minDate, maxDate]);

  return (
    <div className="chartsBox">
      <div className="chartBox">
        <svg width={svgWidth} height={svgHeight} ref={svgRef}>
          <g className="x-axis" />
          <g className="y-axis" />
        </svg>
      </div>
    </div>
  );
};

export default ChartFirstCase;
1 Answers

The path is there, as you can see, but the x coordinates are completely off. The probable reason is that you're using d3.extent on strings. When you do that, 10 comes before 9.

Thus, convert everything to date objects from the beginning, and drop that getDate function:

const dates = allData ? allData.map((data) => new Date(data.Dates)) : [];

However, that's not enough, because you're passing only cases as the data, and passing the indices of each object to the x scale:

const casesLine = line()
  .x((value, index) => xScale(index))
  .y(yScale)
  .curve(curveCardinal);

Instead of that, use a data array that contains both dates and cases and change your line generator accordingly. For instance:

const casesLine = line()
  .x((value) => xScale(value.date))
  .y((value) => yScale(value.case))
  .curve(curveCardinal);
Related