英文:
CanvasJS chart not updating on first page load
问题
我正在开发一个 web 应用程序,我想以折线图的形式呈现数据。为此,我正在使用 CanvasJS 组件 CanvasJSChart。除了当我尝试重新加载页面时,图表未加载之外,一切都运作良好。这 是我重新加载页面时看到的情况。当我然后更新代码(插入新行并保存)时,我看到这。日期时间字段用于筛选哪些日期和时间应该可见,只要在编辑它们时数据点可见,它们就起作用。我发现唯一解决此问题的方法是更新代码或调整窗口大小。
这是我用于创建选项并返回图表组件的代码。
import React from 'react';
import CanvasJSReact from '@canvasjs/react-charts';
const options = {
zoomEnabled: true,
animationEnabled: true,
animationDuration: 1200,
title: {
text: "查看图表"
},
toolTip: {
shared: true,
contentFormatter: function(e){
var content = " ";
for (var i = 0; i < e.entries.length; i++) {
content += e.entries[i].dataSeries.name
+ " " + "<strong>"
+ e.entries[i].dataPoint.y + "</strong>";
content += "<br/>";
}
content += e.entries[0].dataPoint.x + "<br/>";
return content
}
},
data: [
{
type: "line",
name: "温度",
showInLegend: true,
dataPoints: []
},
{
type: "line",
name: "湿度",
showInLegend: true,
dataPoints: []
}]
}
export function GraphFunc(props){
options.data[0].dataPoints = props.data.tempPoints;
options.data[1].dataPoints = props.data.humPoints;
return(
<div>
<CanvasJSReact.CanvasJSChart options={options} />
</div>
)
}
这是调用 API、收集数据点、处理日期选择器并创建图表组件的代码。
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import dayjs from 'dayjs';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { GraphFunc } from './GraphFunc.js';
function formatData(data, lower, upper){
var tmp = {tempPoints: [], humPoints: []};
data.forEach(element => {
var date = new Date(element.date);
if(lower != undefined && upper != undefined){
var epochTime = date.getTime();
if(upper < epochTime || epochTime < lower){
return;
}
}
tmp.tempPoints.push({y: Number(element.temp), x: date})
tmp.humPoints.push({y: Number(element.hum), x: date})
});
console.log("现在我更改东西")
return tmp;
}
export function Graph() {
const [data, getData] = useState('')
const [startDate, setStartValue] = useState(dayjs());
const [endDate, setEndValue] = useState(dayjs());
const [oldStart, setOldStart] = useState(dayjs());
const [oldEnd, setOldEnd] = useState(dayjs());
useEffect(() => {
getAllData(undefined, undefined);
}, []);
const getAllData = (lower, upper) => {
axios.get("/api/dhts/")
.then((res) => {
const d = formatData(res.data, lower, upper)
getData(d);
})
.catch((err) => console.log(err));
}
function handleChanges(e){
if(startDate.$d.getTime() == oldStart.$d.getTime() && endDate.$d.getTime() == oldEnd.$d.getTime()){
return
}
setOldStart(startDate);
setOldEnd(endDate);
getAllData(startDate.$d.getTime(), endDate.$d.getTime());
}
return(
<>
<GraphFunc data={data} />
<div style={{display: "flex", alignItems: "center", justifyContent: "center",}}>
<strong style={{marginBottom: 7, marginTop: 7}}>选择日期以显示数据</strong>
</div>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<div style={{display: "flex", alignItems: "center", justifyContent: "center",}}>
<DateTimePicker value={startDate} onChange={setStartValue} onClose={handleChanges} label="开始日期" />
<DateTimePicker value={endDate} onChange={setEndValue} onClose={handleChanges} label="结束日期" />
</div>
</LocalizationProvider>
</>
)
}
我找到了这个帖子,其中有类似的问题,但我们的程序看起来很不一样。我认为某些地方是异步的,导致图表未加载。但是,我不知道如何修复它。有人有一个快速解决方案吗?
英文:
I am developing a web application where I want to present data in the form of a line graph. For this I am using the CanvasJS component CanvasJSChart. Everything works well except that the graph is not loaded when I try to reload a page. This is what I see when I reload the page. When I then update the code (insert a new line and save) I see this. The datetime fields are used to filter which dates and times that should be visible and they work as long as the data points are visible when I edit them. The only thing I have found that solves this is by updating the code or resizing the window.
This is the code that I use to create the options and return the chart component.
import React from 'react';
import CanvasJSReact from '@canvasjs/react-charts';
const options = {
zoomEnabled: true,
animationEnabled: true,
animationDuration: 1200,
title: {
text: "Graph to see shit"
},
toolTip: {
shared: true,
contentFormatter: function(e){
var content = " ";
for (var i = 0; i < e.entries.length; i++) {
content += e.entries[i].dataSeries.name
+ " " + "<strong>"
+ e.entries[i].dataPoint.y + "</strong>";
content += "<br/>";
}
content += e.entries[0].dataPoint.x + "<br/>";
return content
}
},
data: [
{
type: "line",
name: "Temperature",
showInLegend: true,
dataPoints: []
},
{
type: "line",
name: "Humidity",
showInLegend: true,
dataPoints: []
}]
}
export function GraphFunc(props){
options.data[0].dataPoints = props.data.tempPoints;
options.data[1].dataPoints = props.data.humPoints;
return(
<div>
< CanvasJSReact.CanvasJSChart options={options} />
</div>
)
}
This is the code that calls the API, collects datapoints, handle the date pickers and creates the chart component.
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import dayjs from 'dayjs';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { GraphFunc } from './GraphFunc.js'
function formatData(data, lower, upper){
var tmp = {tempPoints: [], humPoints: []};
data.forEach(element => {
var date = new Date(element.date);
if(lower != undefined && upper != undefined){
var epochTime = date.getTime();
if(upper < epochTime || epochTime < lower){
return;
}
}
tmp.tempPoints.push({y: Number(element.temp), x: date})
tmp.humPoints.push({y: Number(element.hum), x: date})
});
console.log("Nu byter jag saker")
return tmp;
}
export function Graph() {
const [data, getData] = useState('')
const [startDate, setStartValue] = useState(dayjs());
const [endDate, setEndValue] = useState(dayjs());
const [oldStart, setOldStart] = useState(dayjs());
const [oldEnd, setOldEnd] = useState(dayjs());
useEffect(() => {
getAllData(undefined, undefined);
}, []);
const getAllData = (lower, upper) => {
axios.get("/api/dhts/")
.then((res) => {
const d = formatData(res.data, lower, upper)
getData(d);
})
.catch((err) => console.log(err));
}
function handleChanges(e){
if(startDate.$d.getTime() == oldStart.$d.getTime() && endDate.$d.getTime() == oldEnd.$d.getTime()){
return
}
setOldStart(startDate);
setOldEnd(endDate);
getAllData(startDate.$d.getTime(), endDate.$d.getTime());
}
return(
<>
<GraphFunc data={data} />
<div style={{display: "flex", alignItems: "center", justifyContent: "center",}}>
<strong style={{marginBottom: 7, marginTop: 7}}>Pick dates for displaying data</strong>
</div>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<div style={{display: "flex", alignItems: "center", justifyContent: "center",}}>
<DateTimePicker value={startDate} onChange={setStartValue} onClose={handleChanges} label="Start date" />
<DateTimePicker value={endDate} onChange={setEndValue} onClose={handleChanges} label="End date" />
</div>
</LocalizationProvider>
</>
)
}
I found this post which had similar issues but our programs look quite different. I do think that something is asynchronous and that causes this to not load. However, I don't have a clue what could fix it. Is anyone sitting on a quick fix for this?
答案1
得分: -1
尝试将 graphFunc 改成这样,我认为你的问题在于第一次渲染。
虽然数据还没有加载完成,但 React 仍然渲染了组件,而且没有重新渲染以使其再次工作。
但是当你在代码中进行更改时,实际上是重新渲染,因此 DOM 会更新为新的数据。
import React from 'react';
import CanvasJSReact from '@canvasjs/react-charts';
export function GraphFunc(props){
const options = {
zoomEnabled: true,
animationEnabled: true,
animationDuration: 1200,
title: {
text: "查看图表"
},
toolTip: {
shared: true,
contentFormatter: function(e){
var content = " ";
for (var i = 0; i < e.entries.length; i++) {
content += e.entries[i].dataSeries.name
+ " " + "<strong>"
+ e.entries[i].dataPoint.y + "</strong>";
content += "<br/>";
}
content += e.entries[0].dataPoint.x + "<br/>";
return content
}
},
data: [
{
type: "line",
name: "温度",
showInLegend: true,
dataPoints: props.data?.tempPoints
},
{
type: "line",
name: "湿度",
showInLegend: true,
dataPoints: props.data?.humPoints
}
]
}
if (!props.data.humPoints || !props.data.tempPoints) return "加载中";
return(
<div>
<CanvasJSReact.CanvasJSChart options={options} />
</div>
)
}
英文:
Try to make the graphFunc like this, I think ur problem is in the first render.
The data is not here yet but react render the component anyways, and no re-renders to make it work again.
But when u change in code, this is actually a re-render so the DOM updated with the data
import React from 'react';
import CanvasJSReact from '@canvasjs/react-charts';
export function GraphFunc(props){
const options = {
zoomEnabled: true,
animationEnabled: true,
animationDuration: 1200,
title: {
text: "Graph to see shit"
},
toolTip: {
shared: true,
contentFormatter: function(e){
var content = " ";
for (var i = 0; i < e.entries.length; i++) {
content += e.entries[i].dataSeries.name
+ " " + "<strong>"
+ e.entries[i].dataPoint.y + "</strong>";
content += "<br/>";
}
content += e.entries[0].dataPoint.x + "<br/>";
return content
}
},
data: [
{
type: "line",
name: "Temperature",
showInLegend: true,
dataPoints: props.data?.tempPoints
},
{
type: "line",
name: "Humidity",
showInLegend: true,
dataPoints: props.data?.humPoints
}]
}
if (!props.data.humPoints || !props.data.tempPoints) return "Loading";
return(
<div>
<CanvasJSReact.CanvasJSChart options={options} />
</div>
)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论