我正在尝试复制这个例子:https://www.highcharts.com/demo/dynamic-master-detail但使用React(+Hooks(
我的问题是细节图表,因为我已经让master工作了,我知道细节图表将由回调生成(我仍然不太擅长回调概念(
在Highcharts文档中,我可以在chart.events.load中创建回调函数,这是我决定在masterChart中执行的操作
然而,我在createDetails函数(回调函数(中得到一个错误,说
undefined is not an object (evaluating 'masterChart.series[0]')
这很奇怪,因为我在创建masterChart时也做了同样的事情,而且它成功了,所以我认为问题不可能是我的RData对象。
这是我现在的代码:
import React, {useEffect,useState} from 'react';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import RData from '../data/RData'
const RChart = () => {
const[masterChart,setMasterChart] = useState([]);
const[detailChart,setDetailChart] = useState([]);
//updating masterChart
useEffect(()=>{
setMasterChart({
chart: {
reflow: false,
borderWidth: 0,
backgroundColor: "#ffffff",
marginLeft: 50,
marginRight: 20,
zoomType: 'x',
events: {
// listen to the selection event on the master chart to update the
// extremes of the detail chart
selection: function (event) {
var extremesObject = event.xAxis[0],
min = extremesObject.min,
max = extremesObject.max,
detailData = [],
xAxis = this.xAxis[0];
// reverse engineer the last part of the data
RData.each(this.series[0].RData, function () {
if (this.x > min && this.x < max) {
detailData.push([this.x, this.y]);
}
});
// move the plot bands to reflect the new detail span
xAxis.removePlotBand('mask-before');
xAxis.addPlotBand({
id: 'mask-before',
from: RData[0][0],
to: min,
color: 'rgba(0, 0, 0, 0.2)'
});
xAxis.removePlotBand('mask-after');
xAxis.addPlotBand({
id: 'mask-after',
from: max,
to: RData[RData.length - 1][0],
color: 'rgba(255, 255, 0, 0.2)'
});
detailChart.series[0].setData(detailData);
return false;
},
load:createDetail(masterChart) //callback!!
}
},
title: {
text: null
},
accessibility: {
enabled: false
},
xAxis: {
type: 'datetime',
showLastTickLabel: true,
maxZoom: 14 * 24 * 3600000, // fourteen days
plotBands: [{
id: 'mask-before',
from: RData[0][0],
to: RData[RData.length - 1][0],
color: 'rgba(0, 0, 0, 0.2)'
}],
title: {
text: null
}
},
yAxis: {
gridLineWidth: 0,
labels: {
enabled: false
},
title: {
text: null
},
min: 0.6,
showFirstLabel: false
},
tooltip: {
formatter: function () {
return false;
}
},
legend: {
enabled: false
},
credits: {
enabled: false
},
plotOptions: {
series: {
fillColor: {
linearGradient: [0, 0, 0, 255],
stops: [
[0, Highcharts.getOptions().colors[0]],
[1, 'rgba(0,255,255,0)']
]
},
lineWidth: 1,
marker: {
enabled: false
},
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
enableMouseTracking: false
}
},
series: [{
type: 'area',
name: 'USD to EUR',
pointInterval: 24 * 3600 * 1000,
pointStart: RData[0][0],
data: RData
}],
exporting: {
enabled: false
}
})
},[]);
//callback function to create detail chart
const createDetail = (masterChart) => {
// prepare the detail chart
var detailData = [],
detailStart = RData[0][0];
//Error here
RData.each(masterChart.series[0].RData, function () {
if (this.x >= detailStart) {
detailData.push(this.y);
}
});
setDetailChart({
chart: {
marginBottom: 120,
reflow: false,
marginLeft: 50,
marginRight: 20,
style: {
position: 'absolute'
}
},
credits: {
enabled: false
},
title: {
text: 'Historical USD to EUR Exchange Rate',
align: 'left'
},
subtitle: {
text: 'Select an area by dragging across the lower chart',
align: 'left'
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: {
text: null
},
maxZoom: 0.1
},
tooltip: {
formatter: function () {
var point = this.points[0];
return '<b>' + point.series.name + '</b><br/>' + Highcharts.dateFormat('%A %B %e %Y', this.x) + ':<br/>' +
'1 USD = ' + Highcharts.numberFormat(point.y, 2) + ' EUR';
},
shared: true
},
legend: {
enabled: false
},
plotOptions: {
series: {
marker: {
enabled: false,
states: {
hover: {
enabled: true,
radius: 3
}
}
}
}
},
series: [{
name: 'USD to EUR',
pointStart: detailStart,
pointInterval: 24 * 3600 * 1000,
data: detailData
}],
exporting: {
enabled: false
}
});
}
return(
<React.Fragment>
<HighchartsReact highcharts={Highcharts} options={masterChart} />
<HighchartsReact highcharts={Highcharts} options={detailChart} />
</React.Fragment>
);
}
export default RChart;
我愿意接受任何批评和更好的方法。
(已编辑(尝试在空数组中添加setMasterChart和setDetailChart作为效果挂钩的第二个参数。只是个主意。
我认为更好的方法是将Hooks选项设置到一个功能组件中,并将它们作为道具传递到将渲染每个图表的函数中。
演示:https://stackblitz.com/edit/react-lwkgkv?file=index.js