我正在尝试使用reactJS和D3JS(v5)可视化股价图表。
大致分为三部分:
parseData()
。将fetch
中的数据解析为
d3可以读取的格式。已验证工作正常,但包含在
完整性。componentDidMount()
中进行class App
通话。承诺链:先获取调用,然后依次访问parseData()
和setState()
,最后
drawChart()
drawChart()
中的class App
局部函数:包含所有D3逻辑。稍后将被分离成自己的组件。如果我从本地json传递数据(注释掉;下面提供了一些示例行),则有效,但是当我尝试传递数据时不起作用
来自fetch
的数据。到目前为止的代码:全部包含在App.js
中,没有子组件:
import React, { Component } from 'react';
import './App.css';
import * as d3 from "d3";
//import testTimeData from "./data/testTimeData"
function parseData(myInput) {
// processes alpha vantage data into a format for viz
// output an array of objects,
// where each object is {"Date":"yyyy-mm-dd", "a":<float>}
let newArray = []
for (var key in myInput) {
if (myInput.hasOwnProperty(key)) {
const newRow = Object.assign({"newDate": new Date(key)}, {"Date": key}, myInput[key])
newArray.push(newRow)
}
}
//console.log(newArray)
// 2. Generate plotData for d3js
let newArray2 = []
for (var i = 0; i < newArray.length; i++) {
let newRow = Object.assign({"Date": newArray[i]["Date"]}, {"a":parseFloat(newArray[i]["4. close"])})
newArray2.unshift(newRow)
}
return newArray2
}
class App extends Component {
constructor() {
super()
this.state = {
ticker:"",
plotData:[]
}
this.drawChart = this.drawChart.bind(this)
}
// setState() in componentDidMount()
// fetch monthly data
// hardcode ticker = VTSAX for the moment
// and call this.drawChart()
componentDidMount() {
const ticker = "VTSAX"
const api_key = "EEKL6B77HNZE6EB4"
fetch("https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol="+ticker+"&apikey="+api_key)
.then(console.log("fetching..."))
.then(response => response.json())
.then(data => parseData(data["Monthly Time Series"]))
.then(data => console.log(data))
.then(data =>{this.setState({plotData:data, ticker:ticker})})
.then(this.drawChart());
}
drawChart() {
const stockPlotData = this.state.plotData
console.log("stockPlotData.length=", stockPlotData.length)
var svg = d3.select("body").append("svg")
.attr("width", 960)
.attr("height", 300)
var margin = {left:50, right:30, top:30, bottom: 30}
var width = svg.attr("width") - margin.left - margin.right;
var height = svg.attr("height") - margin.bottom - margin.top;
var x = d3.scaleTime().rangeRound([0, width]);
var y = d3.scaleLinear().rangeRound([height, 0]);
var parseTime = d3.timeParse("%Y-%m-%d");
x.domain(d3.extent(stockPlotData, function(d) { return parseTime(d.date); }));
y.domain([0,
d3.max(stockPlotData, function(d) {
return d.a;
})]);
var multiline = function(category) {
var line = d3.line()
.x(function(d) { return x(parseTime(d.date)); })
.y(function(d) { return y(d[category]); });
return line;
}
var g = svg.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
var categories = ['a'];
for (let i in categories) {
var lineFunction = multiline(categories[i]);
g.append("path")
.datum(stockPlotData)
.attr("class", "line")
.style("stroke", "blue")
//.style("stroke", color(i))
.style("fill", "None")
.attr("d", lineFunction);
}
// append X Axis
g.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%Y-%m-%d")));
// append Y Axis
g.append("g")
.call(d3.axisLeft(y));
}
render(){
return (<div>{this.state.ticker}</div>)
}
}
export default App;
来自console.log()
调用的输出:
data => console.log(data)
的承诺链中的componentDidMount()
正确显示提取的数据console.log("stockPlotData.length=", stockPlotData.length)
函数中的drawChart()
调用返回stockPlotData.length= 0
。我打错了this.setState()
吗?render(){return(...)}
调用中正确呈现了“ VTSAX”,指示this.setState
正确更新了ticker
变量。一些测试数据行:
[
{"Date":"2016-01-15", "a": 220 },
{"Date":"2016-01-16", "a": 250},
{"Date":"2016-01-17", "a": 130},
{"Date":"2016-01-18", "a": 180},
{"Date":"2016-01-19", "a": 200},
]
答案 0 :(得分:0)
要阅读的代码很多,但是基于快速浏览,您可能希望在.then内部而不是在promise链之后调用this.drawChart(),因为它会在您的promise兑现之前触发。 / p>