react d3 - using data from csv - <path> attribute d: Expected number, "M0,NaNC0,NaN,50,NaN…"

672 Views Asked by At

I'm trying to create my first react-d3 line charts and I'm having trouble getting it right. I feel like I'm pretty close but I can't figure this part out.

I have a CSV that I'm trying to read data from to get this chart going. I've found other examples but they are dealing with JSON or an array and my js skills aren't there yet unfortunately.

I'm getting this error: (I've seen other posts on SO that have this same error but I didn't see a solution that fit my problem.)

attr.js:30 Error: <path> attribute d: Expected number, "MNaN,NaNCNaN,NaN,…".

Here is my code:

import React, { useRef, useEffect, useState } from "react";
import * as d3 from "d3";
import csvData from "../sandbox.csv";



import {
  select,
  line,
  curveCardinal,
  axisBottom,
  axisRight,
  scaleLinear,
} from "d3";

function ActionsLineGraph() {
  const [data, setData] = useState(null);
  // const [loading, setLoading] = React.useState(true);


  // const [data, setData] = useState([25, 30, 45, 60, 20, 65, 75]);
  const svgRef = useRef();

  // will be called initially and on every data change
  useEffect(() => {
    d3.csv(csvData).then((data) => {
      console.log("Fetching Data");
      console.log(data);
      setData(data);
      // setLoading(false);

      const svg = select(svgRef.current);
      const xScale = scaleLinear()
        .domain([0, data.length - 1])
        .range([0, 300]);

      const yScale = scaleLinear().domain([0, 150]).range([150, 0]);

      const xAxis = axisBottom(xScale)
        .ticks(data.length)
        .tickFormat((index) => index + 1);
      svg.select(".x-axis").style("transform", "translateY(150px)").call(xAxis);

      const yAxis = axisRight(yScale);
      svg.select(".y-axis").style("transform", "translateX(300px)").call(yAxis);

      // generates the "d" attribute of a path element
      const myLine = line()
        .x((value, index) => {
          console.log("index: " + index);
          xScale(index)
        })
        .y(yScale)
        .curve(curveCardinal);

        console.log("myLine: " + myLine);
        

      // renders path element, and attaches
      // the "d" attribute from line generator above
      svg. // <--- i believe error is happening somewhere in this block.
        .selectAll(".line")
        .data([data])
        .join("path")
        .attr("class", "line")
        .attr("d", myLine)
        .attr("fill", "none")
        .attr("stroke", "blue");
    });
  }, [/* data */]);

  return (
    <React.Fragment>
      <svg ref={svgRef}>
        <g className="x-axis" />
        <g className="y-axis" />
      </svg>
      <br />
      <br />
      <br />
      <br />
      <button onClick={() => setData(data.map((value) => value + 5))}>
        Update data
      </button>
      <button onClick={() => setData(data.filter((value) => value < 35))}>
        Filter data
      </button>
    </React.Fragment>
  );
}

export default ActionsLineGraph;

Here are the contents of my CSV:

date,added,updated,deleted
2021-09-15,10,9,8
2021-09-16,20,11,7
2021-09-17,15,12,9
2021-09-18,20,9,8
2021-09-19,20,9,8

Any help or direction is appreciated!

1

There are 1 best solutions below

0
On

so I kind of resolved it on my own.

from what I found, when you return d.date or d.added they are automatically returned as strings instead of a timestamp or a number as intented so I had to parse it out and it seems to have kind of worked.

I added this code and it helps

var parseTime = d3.timeParse("%Y-%m-%d");

const myLine = d3.line()
   .x((d) => { return x(parseTime(d.date)); })
   .y((d) => { return y(Number(d.added)); });
svg
   .append("path")
   .data([data])
   .attr("class", "line")
   .attr("fill", "none")
   .attr("stroke", "steelblue")
   .attr("stroke-width", 1.5)
   .attr("d", myLine);

my graph isn't showing but the scales are but at least there are no errors. one step forward.