Error: <path> attribute d: Expected number, "MNaN,36.393574100…

Error: <path> attribute d: Expected number, "MNaN,36.393574100…

我正在尝试使用 d3.js 构建一个简单的折线图并将其呈现在反应组件中。不幸的是,我收到以下错误:

Error: <path> attribute d: Expected number, "MNaN,36.393574100…"

不幸的是Whosebug的类似问题对我帮助不大。我的理论是,当我将路径附加到图表时,我没有正确读取数据对象 (data.forEach) 到我的“d”属性。我已经尝试使用和不使用 parseDate 函数来执行此操作。当我在没有它的情况下这样做时,我的日期看起来应该如何在控制台中显示。如果我稍后在代码中包含 parseDate 函数,同时我在路径 d 属性的 x 函数中声明我的 x 轴 and/or ......没有什么真正改变。我也不完全确定我的数据对象是否正确嵌套,或者我是否应该将整个数据对象提供给 datum() 函数....

这是我的代码:

import * as d3 from "d3";
import React, { useRef, useEffect } from "react";

function LineBarChart({ width, height, data }) {

const ref = useRef();

useEffect(() => {
 d3.select(ref.current)
  .attr("width", width)
  .attr("height", height)
  // .style("border", "1px solid black");
  }, [height, width]);

 useEffect(() => {
  draw();
 }, [data]);

const draw = () => {

const parseDate = d3.timeFormat("%Y-%m-%d");

data.forEach(function (d) {
 d.dateM = d.dateM;
 // d.dateM = parseDate(d.dateM);
 d.closeM = +d.closeM;
 console.log("WHAT-DO-I-LOOK-LIKE", d.dateM)
});

// const dataNest = d3.nest()
//   .key((d) => d.dateM)
//   .key((d) => d.closeM)
//   .map(data);

const margin = 80;
const width = 1400 - 2 * margin;
const height = 800 - 2 * margin;

const svg = d3.select(ref.current);

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


 var x = d3.scaleTime()
  .domain(d3.extent(data, function(d) { return d.dateM; }))
  //.domain(d3.extent(data, function(d) { return parseDate(d.dateM); }))
  .range([ 0, width ]);

 chart.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x));

 var y = d3.scaleLinear()
   .domain([0, d3.max(data, function(d) { return +d.closeM; })])
   .range([ height, 0 ]);

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

 chart.append("path")
  .datum(data)
  .attr('class', 'lineChartClass')
  .attr("fill", "none")
  .attr("stroke", "steelblue")
  .attr("stroke-width", 1.5)
  .attr("d", d3.line()
    // .x(function(d) { return parseDate(d.dateM) })
    .x(function(d) { return x(d.dateM) })
    .y(function(d) { return y(d.closeM) })

  )

}; //draw

return (
 <div className="chartSixPointFive">
  <svg ref={ref}></svg>
 </div>

);
}

export default LineBarChart;

我的 React 应用程序使用 Axios 来访问 Flask 端点。这里没有什么特别的,我只是 return 这样的线图。

....
....
<LineBarChart width={1350} height={1000} data={data} />

如有必要,我可以包含完整的 React 代码(尽管我认为不需要)

这是我的数据对象的样子:

    "results": [
    {
        "date": "2022-02-07",
        "open": 172.860001,
        "high": 173.949997,
        "low": 170.949997,
        "close": 171.660004,
        "volume": 77045100,
        "adjClose": 171.660004
    },

    rinse & repeat ....
    
    ]

我很感激能得到的任何帮助!

d3.timeFormat 格式化日期对象和 returns 一个 字符串 。你想要的是 d3.timeParse 相反,它会做相反的事情:它将你的字符串解析为日期对象,可以由时间尺度使用:

const parseDate = d3.timeParse("%Y-%m-%d");

PS"d" 属性的 M 命令使用(几乎所有语言中的所有内容)坐标对 x,y (horizontal/vertical)。因此,当您遇到错误时:

MNaN,42...

...您知道问题出在您的 x 刻度上,而错误:

M42,NaN...

...显示问题出在 y 尺度上。