CanvasJS 图表在第一次页面加载时没有更新。

huangapple go评论81阅读模式
英文:

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 &#39;react&#39;;
import CanvasJSReact from &#39;@canvasjs/react-charts&#39;;

const options = {
    zoomEnabled: true,
    animationEnabled: true,
    animationDuration: 1200,
    title: {
        text: &quot;Graph to see shit&quot;
    },

    toolTip: {
        shared: true,
        contentFormatter: function(e){
            var content = &quot; &quot;;
            for (var i = 0; i &lt; e.entries.length; i++) {
                content += e.entries[i].dataSeries.name 
                        + &quot; &quot; + &quot;&lt;strong&gt;&quot; 
                        + e.entries[i].dataPoint.y + &quot;&lt;/strong&gt;&quot;;
                content += &quot;&lt;br/&gt;&quot;;
            }
            content += e.entries[0].dataPoint.x + &quot;&lt;br/&gt;&quot;;
            return content
        }
    },

    data: [
    {
        type: &quot;line&quot;,
        name: &quot;Temperature&quot;,
        showInLegend: true,
        dataPoints: []
    },
    {
        type: &quot;line&quot;,
        name: &quot;Humidity&quot;,
        showInLegend: true,
        dataPoints: []
    }]
}

export function GraphFunc(props){

    options.data[0].dataPoints = props.data.tempPoints;
    options.data[1].dataPoints = props.data.humPoints;
    return(
    &lt;div&gt;
        &lt; CanvasJSReact.CanvasJSChart options={options} /&gt;
    &lt;/div&gt;
    )
}

This is the code that calls the API, collects datapoints, handle the date pickers and creates the chart component.

import React, { useState, useEffect } from &#39;react&#39;;
import axios from &#39;axios&#39;;
import dayjs from &#39;dayjs&#39;;
import { AdapterDayjs } from &#39;@mui/x-date-pickers/AdapterDayjs&#39;;
import { DateTimePicker } from &#39;@mui/x-date-pickers/DateTimePicker&#39;;
import { LocalizationProvider } from &#39;@mui/x-date-pickers&#39;;
import { GraphFunc } from &#39;./GraphFunc.js&#39;

function formatData(data, lower, upper){
  var tmp = {tempPoints: [], humPoints: []};

  data.forEach(element =&gt; {
    var date = new Date(element.date);
    
    if(lower != undefined &amp;&amp; upper != undefined){
      var epochTime = date.getTime();
      
      if(upper &lt; epochTime || epochTime &lt; lower){
        return;
      }
    }

    tmp.tempPoints.push({y: Number(element.temp), x: date})
    tmp.humPoints.push({y: Number(element.hum), x: date})
  });
  console.log(&quot;Nu byter jag saker&quot;)
  return tmp;
}

export function Graph() {

  const [data, getData] = useState(&#39;&#39;)
  const [startDate, setStartValue] = useState(dayjs());
  const [endDate, setEndValue] = useState(dayjs());
  const [oldStart, setOldStart] = useState(dayjs());
  const [oldEnd, setOldEnd] = useState(dayjs());
  
  useEffect(() =&gt; {
    getAllData(undefined, undefined);
  }, []);

  const getAllData = (lower, upper) =&gt; {
    axios.get(&quot;/api/dhts/&quot;)
        .then((res) =&gt; {
          const d = formatData(res.data, lower, upper)
          getData(d);
        })
        .catch((err) =&gt; console.log(err));
  }

  function handleChanges(e){
    if(startDate.$d.getTime() == oldStart.$d.getTime() &amp;&amp; endDate.$d.getTime() == oldEnd.$d.getTime()){
      return
    }
    
    setOldStart(startDate);
    setOldEnd(endDate);

    getAllData(startDate.$d.getTime(), endDate.$d.getTime());
  }


  return(
    &lt;&gt;
    &lt;GraphFunc data={data} /&gt;

    &lt;div style={{display: &quot;flex&quot;, alignItems: &quot;center&quot;, justifyContent: &quot;center&quot;,}}&gt;
        &lt;strong style={{marginBottom: 7, marginTop: 7}}&gt;Pick dates for displaying data&lt;/strong&gt;
    &lt;/div&gt;  

    &lt;LocalizationProvider dateAdapter={AdapterDayjs}&gt;
      &lt;div style={{display: &quot;flex&quot;, alignItems: &quot;center&quot;, justifyContent: &quot;center&quot;,}}&gt;
          &lt;DateTimePicker value={startDate} onChange={setStartValue} onClose={handleChanges} label=&quot;Start date&quot; /&gt;
          &lt;DateTimePicker value={endDate} onChange={setEndValue} onClose={handleChanges} label=&quot;End date&quot; /&gt;
      &lt;/div&gt;  
    &lt;/LocalizationProvider&gt;  
    &lt;/&gt;
  )
}

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 &#39;react&#39;;
import CanvasJSReact from &#39;@canvasjs/react-charts&#39;;
export function GraphFunc(props){
const options = {
zoomEnabled: true,
animationEnabled: true,
animationDuration: 1200,
title: {
text: &quot;Graph to see shit&quot;
},
toolTip: {
shared: true,
contentFormatter: function(e){
var content = &quot; &quot;;
for (var i = 0; i &lt; e.entries.length; i++) {
content += e.entries[i].dataSeries.name 
+ &quot; &quot; + &quot;&lt;strong&gt;&quot; 
+ e.entries[i].dataPoint.y + &quot;&lt;/strong&gt;&quot;;
content += &quot;&lt;br/&gt;&quot;;
}
content += e.entries[0].dataPoint.x + &quot;&lt;br/&gt;&quot;;
return content
}
},
data: [
{
type: &quot;line&quot;,
name: &quot;Temperature&quot;,
showInLegend: true,
dataPoints: props.data?.tempPoints
},
{
type: &quot;line&quot;,
name: &quot;Humidity&quot;,
showInLegend: true,
dataPoints: props.data?.humPoints
}]
}
if (!props.data.humPoints || !props.data.tempPoints) return &quot;Loading&quot;;
return(
&lt;div&gt;
&lt;CanvasJSReact.CanvasJSChart options={options} /&gt;
&lt;/div&gt;
)
}

huangapple
  • 本文由 发表于 2023年6月29日 01:21:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76575424.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定