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

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

CanvasJS chart not updating on first page load

问题

我正在开发一个 web 应用程序,我想以折线图的形式呈现数据。为此,我正在使用 CanvasJS 组件 CanvasJSChart。除了当我尝试重新加载页面时,图表未加载之外,一切都运作良好。 是我重新加载页面时看到的情况。当我然后更新代码(插入新行并保存)时,我看到。日期时间字段用于筛选哪些日期和时间应该可见,只要在编辑它们时数据点可见,它们就起作用。我发现唯一解决此问题的方法是更新代码或调整窗口大小。

这是我用于创建选项并返回图表组件的代码。

  1. import React from 'react';
  2. import CanvasJSReact from '@canvasjs/react-charts';
  3. const options = {
  4. zoomEnabled: true,
  5. animationEnabled: true,
  6. animationDuration: 1200,
  7. title: {
  8. text: "查看图表"
  9. },
  10. toolTip: {
  11. shared: true,
  12. contentFormatter: function(e){
  13. var content = " ";
  14. for (var i = 0; i < e.entries.length; i++) {
  15. content += e.entries[i].dataSeries.name
  16. + " " + "<strong>"
  17. + e.entries[i].dataPoint.y + "</strong>";
  18. content += "<br/>";
  19. }
  20. content += e.entries[0].dataPoint.x + "<br/>";
  21. return content
  22. }
  23. },
  24. data: [
  25. {
  26. type: "line",
  27. name: "温度",
  28. showInLegend: true,
  29. dataPoints: []
  30. },
  31. {
  32. type: "line",
  33. name: "湿度",
  34. showInLegend: true,
  35. dataPoints: []
  36. }]
  37. }
  38. export function GraphFunc(props){
  39. options.data[0].dataPoints = props.data.tempPoints;
  40. options.data[1].dataPoints = props.data.humPoints;
  41. return(
  42. <div>
  43. <CanvasJSReact.CanvasJSChart options={options} />
  44. </div>
  45. )
  46. }

这是调用 API、收集数据点、处理日期选择器并创建图表组件的代码。

  1. import React, { useState, useEffect } from 'react';
  2. import axios from 'axios';
  3. import dayjs from 'dayjs';
  4. import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
  5. import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker';
  6. import { LocalizationProvider } from '@mui/x-date-pickers';
  7. import { GraphFunc } from './GraphFunc.js';
  8. function formatData(data, lower, upper){
  9. var tmp = {tempPoints: [], humPoints: []};
  10. data.forEach(element => {
  11. var date = new Date(element.date);
  12. if(lower != undefined && upper != undefined){
  13. var epochTime = date.getTime();
  14. if(upper < epochTime || epochTime < lower){
  15. return;
  16. }
  17. }
  18. tmp.tempPoints.push({y: Number(element.temp), x: date})
  19. tmp.humPoints.push({y: Number(element.hum), x: date})
  20. });
  21. console.log("现在我更改东西")
  22. return tmp;
  23. }
  24. export function Graph() {
  25. const [data, getData] = useState('')
  26. const [startDate, setStartValue] = useState(dayjs());
  27. const [endDate, setEndValue] = useState(dayjs());
  28. const [oldStart, setOldStart] = useState(dayjs());
  29. const [oldEnd, setOldEnd] = useState(dayjs());
  30. useEffect(() => {
  31. getAllData(undefined, undefined);
  32. }, []);
  33. const getAllData = (lower, upper) => {
  34. axios.get("/api/dhts/")
  35. .then((res) => {
  36. const d = formatData(res.data, lower, upper)
  37. getData(d);
  38. })
  39. .catch((err) => console.log(err));
  40. }
  41. function handleChanges(e){
  42. if(startDate.$d.getTime() == oldStart.$d.getTime() && endDate.$d.getTime() == oldEnd.$d.getTime()){
  43. return
  44. }
  45. setOldStart(startDate);
  46. setOldEnd(endDate);
  47. getAllData(startDate.$d.getTime(), endDate.$d.getTime());
  48. }
  49. return(
  50. <>
  51. <GraphFunc data={data} />
  52. <div style={{display: "flex", alignItems: "center", justifyContent: "center",}}>
  53. <strong style={{marginBottom: 7, marginTop: 7}}>选择日期以显示数据</strong>
  54. </div>
  55. <LocalizationProvider dateAdapter={AdapterDayjs}>
  56. <div style={{display: "flex", alignItems: "center", justifyContent: "center",}}>
  57. <DateTimePicker value={startDate} onChange={setStartValue} onClose={handleChanges} label="开始日期" />
  58. <DateTimePicker value={endDate} onChange={setEndValue} onClose={handleChanges} label="结束日期" />
  59. </div>
  60. </LocalizationProvider>
  61. </>
  62. )
  63. }

我找到了这个帖子,其中有类似的问题,但我们的程序看起来很不一样。我认为某些地方是异步的,导致图表未加载。但是,我不知道如何修复它。有人有一个快速解决方案吗?

英文:

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.

  1. import React from &#39;react&#39;;
  2. import CanvasJSReact from &#39;@canvasjs/react-charts&#39;;
  3. const options = {
  4. zoomEnabled: true,
  5. animationEnabled: true,
  6. animationDuration: 1200,
  7. title: {
  8. text: &quot;Graph to see shit&quot;
  9. },
  10. toolTip: {
  11. shared: true,
  12. contentFormatter: function(e){
  13. var content = &quot; &quot;;
  14. for (var i = 0; i &lt; e.entries.length; i++) {
  15. content += e.entries[i].dataSeries.name
  16. + &quot; &quot; + &quot;&lt;strong&gt;&quot;
  17. + e.entries[i].dataPoint.y + &quot;&lt;/strong&gt;&quot;;
  18. content += &quot;&lt;br/&gt;&quot;;
  19. }
  20. content += e.entries[0].dataPoint.x + &quot;&lt;br/&gt;&quot;;
  21. return content
  22. }
  23. },
  24. data: [
  25. {
  26. type: &quot;line&quot;,
  27. name: &quot;Temperature&quot;,
  28. showInLegend: true,
  29. dataPoints: []
  30. },
  31. {
  32. type: &quot;line&quot;,
  33. name: &quot;Humidity&quot;,
  34. showInLegend: true,
  35. dataPoints: []
  36. }]
  37. }
  38. export function GraphFunc(props){
  39. options.data[0].dataPoints = props.data.tempPoints;
  40. options.data[1].dataPoints = props.data.humPoints;
  41. return(
  42. &lt;div&gt;
  43. &lt; CanvasJSReact.CanvasJSChart options={options} /&gt;
  44. &lt;/div&gt;
  45. )
  46. }

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

  1. import React, { useState, useEffect } from &#39;react&#39;;
  2. import axios from &#39;axios&#39;;
  3. import dayjs from &#39;dayjs&#39;;
  4. import { AdapterDayjs } from &#39;@mui/x-date-pickers/AdapterDayjs&#39;;
  5. import { DateTimePicker } from &#39;@mui/x-date-pickers/DateTimePicker&#39;;
  6. import { LocalizationProvider } from &#39;@mui/x-date-pickers&#39;;
  7. import { GraphFunc } from &#39;./GraphFunc.js&#39;
  8. function formatData(data, lower, upper){
  9. var tmp = {tempPoints: [], humPoints: []};
  10. data.forEach(element =&gt; {
  11. var date = new Date(element.date);
  12. if(lower != undefined &amp;&amp; upper != undefined){
  13. var epochTime = date.getTime();
  14. if(upper &lt; epochTime || epochTime &lt; lower){
  15. return;
  16. }
  17. }
  18. tmp.tempPoints.push({y: Number(element.temp), x: date})
  19. tmp.humPoints.push({y: Number(element.hum), x: date})
  20. });
  21. console.log(&quot;Nu byter jag saker&quot;)
  22. return tmp;
  23. }
  24. export function Graph() {
  25. const [data, getData] = useState(&#39;&#39;)
  26. const [startDate, setStartValue] = useState(dayjs());
  27. const [endDate, setEndValue] = useState(dayjs());
  28. const [oldStart, setOldStart] = useState(dayjs());
  29. const [oldEnd, setOldEnd] = useState(dayjs());
  30. useEffect(() =&gt; {
  31. getAllData(undefined, undefined);
  32. }, []);
  33. const getAllData = (lower, upper) =&gt; {
  34. axios.get(&quot;/api/dhts/&quot;)
  35. .then((res) =&gt; {
  36. const d = formatData(res.data, lower, upper)
  37. getData(d);
  38. })
  39. .catch((err) =&gt; console.log(err));
  40. }
  41. function handleChanges(e){
  42. if(startDate.$d.getTime() == oldStart.$d.getTime() &amp;&amp; endDate.$d.getTime() == oldEnd.$d.getTime()){
  43. return
  44. }
  45. setOldStart(startDate);
  46. setOldEnd(endDate);
  47. getAllData(startDate.$d.getTime(), endDate.$d.getTime());
  48. }
  49. return(
  50. &lt;&gt;
  51. &lt;GraphFunc data={data} /&gt;
  52. &lt;div style={{display: &quot;flex&quot;, alignItems: &quot;center&quot;, justifyContent: &quot;center&quot;,}}&gt;
  53. &lt;strong style={{marginBottom: 7, marginTop: 7}}&gt;Pick dates for displaying data&lt;/strong&gt;
  54. &lt;/div&gt;
  55. &lt;LocalizationProvider dateAdapter={AdapterDayjs}&gt;
  56. &lt;div style={{display: &quot;flex&quot;, alignItems: &quot;center&quot;, justifyContent: &quot;center&quot;,}}&gt;
  57. &lt;DateTimePicker value={startDate} onChange={setStartValue} onClose={handleChanges} label=&quot;Start date&quot; /&gt;
  58. &lt;DateTimePicker value={endDate} onChange={setEndValue} onClose={handleChanges} label=&quot;End date&quot; /&gt;
  59. &lt;/div&gt;
  60. &lt;/LocalizationProvider&gt;
  61. &lt;/&gt;
  62. )
  63. }

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 会更新为新的数据。

  1. import React from 'react';
  2. import CanvasJSReact from '@canvasjs/react-charts';
  3. export function GraphFunc(props){
  4. const options = {
  5. zoomEnabled: true,
  6. animationEnabled: true,
  7. animationDuration: 1200,
  8. title: {
  9. text: "查看图表"
  10. },
  11. toolTip: {
  12. shared: true,
  13. contentFormatter: function(e){
  14. var content = " ";
  15. for (var i = 0; i < e.entries.length; i++) {
  16. content += e.entries[i].dataSeries.name
  17. + " " + "<strong>"
  18. + e.entries[i].dataPoint.y + "</strong>";
  19. content += "<br/>";
  20. }
  21. content += e.entries[0].dataPoint.x + "<br/>";
  22. return content
  23. }
  24. },
  25. data: [
  26. {
  27. type: "line",
  28. name: "温度",
  29. showInLegend: true,
  30. dataPoints: props.data?.tempPoints
  31. },
  32. {
  33. type: "line",
  34. name: "湿度",
  35. showInLegend: true,
  36. dataPoints: props.data?.humPoints
  37. }
  38. ]
  39. }
  40. if (!props.data.humPoints || !props.data.tempPoints) return "加载中";
  41. return(
  42. <div>
  43. <CanvasJSReact.CanvasJSChart options={options} />
  44. </div>
  45. )
  46. }
英文:

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

  1. import React from &#39;react&#39;;
  2. import CanvasJSReact from &#39;@canvasjs/react-charts&#39;;
  3. export function GraphFunc(props){
  4. const options = {
  5. zoomEnabled: true,
  6. animationEnabled: true,
  7. animationDuration: 1200,
  8. title: {
  9. text: &quot;Graph to see shit&quot;
  10. },
  11. toolTip: {
  12. shared: true,
  13. contentFormatter: function(e){
  14. var content = &quot; &quot;;
  15. for (var i = 0; i &lt; e.entries.length; i++) {
  16. content += e.entries[i].dataSeries.name
  17. + &quot; &quot; + &quot;&lt;strong&gt;&quot;
  18. + e.entries[i].dataPoint.y + &quot;&lt;/strong&gt;&quot;;
  19. content += &quot;&lt;br/&gt;&quot;;
  20. }
  21. content += e.entries[0].dataPoint.x + &quot;&lt;br/&gt;&quot;;
  22. return content
  23. }
  24. },
  25. data: [
  26. {
  27. type: &quot;line&quot;,
  28. name: &quot;Temperature&quot;,
  29. showInLegend: true,
  30. dataPoints: props.data?.tempPoints
  31. },
  32. {
  33. type: &quot;line&quot;,
  34. name: &quot;Humidity&quot;,
  35. showInLegend: true,
  36. dataPoints: props.data?.humPoints
  37. }]
  38. }
  39. if (!props.data.humPoints || !props.data.tempPoints) return &quot;Loading&quot;;
  40. return(
  41. &lt;div&gt;
  42. &lt;CanvasJSReact.CanvasJSChart options={options} /&gt;
  43. &lt;/div&gt;
  44. )
  45. }

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:

确定