Reputation: 1190
D3 Line chart within a React Component with Redux implementation.
Managed to draw xAxis and yAxis but line path is: MNaN,36LNaN,28.000000000000007LNaN,36LNaN,20LNaN,20LNaN,30.666666666666664LNaN,28.000000000000007LNaN,24.000000000000004
Data comes from nextProps in getDerivedStateFromProps lifecycle but not being passed into the lineGenerator.
This is my component:
import * as d3 from 'd3';
import React, { Component } from 'react';
const width = 400;
const height = 200;
const margin = { top: 20, right: 5, bottom: 20, left: 35 };
const green = '#00ded0';
class CPULineChart extends Component {
state = {
cpu: null, // svg path command for all cpu points
// d3 helpers
xScale: d3.scaleTime().range([margin.left, width - margin.right]),
yScale: d3.scaleLinear().range([height - margin.bottom, margin.top]),
lineGenerator: d3.line()
};
xAxis = d3
.axisBottom()
.scale(this.state.xScale)
.tickFormat(d3.timeFormat('%b'));
yAxis = d3.axisBottom().scale(this.state.yScale);
static getDerivedStateFromProps(nextProps, prevState) {
if (!nextProps.data) return null; // data hasn't been loaded yet so do nothing
const { data } = nextProps;
const { yScale, xScale, lineGenerator } = prevState;
// data has changed, so recalculate scale domains
const timeDomain = d3.extent(data, d => d.date);
const cpuMax = d3.max(data, d => d.high);
xScale.domain(timeDomain);
yScale.domain([0, cpuMax]);
// Calculate line for CPU
lineGenerator.x(d => xScale(d.date));
lineGenerator.y(d => yScale(d.high));
const cpu = lineGenerator(data);
console.log(cpu);
return cpu;
}
componentDidUpdate() {
d3.select(this.refs.xAxis).call(this.xAxis);
d3.select(this.refs.yAxis).call(this.yAxis);
}
render() {
return (
<svg width={width} height={height}>
<path d={this.state.cpu} fill="none" stroke={green} strokeWidth="2" />
<g ref="xAxis" transform={`translate(0, ${height - margin.bottom})`} />
<g ref="yAxis" transform={`translate(${margin.left}, 0)`} />
</svg>
);
}
}
export default CPULineChart;
Passing data from parent component:
<CPULineChart data={data} />
And data
{
"date": "2015-10-1 1:00 PM GMT+1:00",
"high": 0.135,
"low": 20
},
{
"date": "2015-10-1 2:00 PM GMT+1:00",
"high": 0.09,
"low": 20
},
{
"date": "2015-10-1 3:00 PM GMT+1:00",
"high": 0.1,
"low": 20
}
Upvotes: 2
Views: 1113
Reputation: 1190
With xScale: d3.scaleTime()...
x values needs to be a Date()
objects. Passed/fetched data contains date
properties provided as strings - needs conversion. timeDomain
used for xScale
needs to be date related, too.
Problem can be solved by changing these two lines:
const timeDomain = d3.extent(data, d => new Date(d.date));
and same in lineGenerator:
lineGenerator.x(d => xScale(new Date(d.date)));
Upvotes: 1