简体   繁体   English

闪电 JS 图表导致崩溃并且无法正确显示数据

[英]Lightning JS Chart causing crashes and not showing data correctly

I have a component that I want to show a graph with multiple line series representing price changes over the last 24 hours.我有一个组件,我想显示一个包含多个线系列的图表,代表过去 24 小时内的价格变化。 I have an endpoint that sends this data and I use the code below to show it.我有一个发送此数据的端点,我使用下面的代码来显示它。

One of the issues comes from errors seeming to come from the library itself meaning the graph will not even show up.其中一个问题来自似乎来自库本身的错误,这意味着图表甚至不会出现。 Errors from the console when I load the page .加载页面时来自控制台的错误

Other times, the page will load for a second and then go white and drain enough CPU to cause a crash.其他时候,页面将加载一秒钟,然后 go 白色并耗尽足够的 CPU 导致崩溃。

The few times that the graph actually shows up on screen, it does not show any lines until the lines 81-85 are uncommented which it then shows the lines but does not zoom in on them leaving a mess on the screen.图形实际显示在屏幕上的几次,它不显示任何线条,直到第 81-85 行被取消注释,然后它显示线条但不放大它们,在屏幕上留下一团糟。

Any help would be much appreciated.任何帮助将非常感激。

/* eslint-disable new-cap */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-magic-numbers */
import React, { useEffect, useState } from "react";
import { LegendBoxBuilders, lightningChart, Themes } from "@arction/lcjs";
import "./TopCurrencyGraph.css";
import axios from "axios";
export interface data {
  data: dataPoint[];
}

export interface dataPoint {
  currency: string;
  percentage: number;
  timestamp: string;
}

interface graphPoint {
  x: number;
  y: number;
}

const TopCurrencyGraph = () => {
  const historicalAddr = `http://${
    process.env.back || "localhost:8000"
  }/historical24hChangeData`;

  useEffect(() => {
    const map: { [name: string]: graphPoint[] } = {};
    axios
      .get(historicalAddr)
      .then((res) => {
        const { points } = res.data;
        const pointList = points as dataPoint[];
        pointList.forEach((obj) => {
          const newPoint = {
            x: new Date(obj.timestamp).getTime() * (60 * 24),
            y: obj.percentage * 100,
          };
          if (obj.currency in map) {
            map[obj.currency].push(newPoint);
          } else {
            map[obj.currency] = [newPoint];
          }
        });
      })
      .catch((err) => {
        console.log(err, historicalAddr);
      });
    const chart = lightningChart().ChartXY({
      theme: Themes.lightNew,
      container: "currency-graph",
    });
    chart.setTitle("Top Currencies");
    chart.getDefaultAxisX().setTitle("Time");
    chart.getDefaultAxisY().setTitle("Percentage Change");

    const entries = Object.entries(map);
    const names = entries.map(([a, _b]) => a);
    const lists = entries.map(([_, b]) => b);

    const seriesArray = new Array(5).fill(null).map((_, idx) =>
      chart
        .addLineSeries({
          dataPattern: {
            pattern: "ProgressiveX",
          },
        })
        // eslint-disable-next-line arrow-parens
        .setStrokeStyle((stroke) => stroke.setThickness(1))
        .setName(names[idx])
    );

    seriesArray.forEach((series, idx) => {
      if (idx === 1) {
        series.add(lists[idx]);
      }
    });

    chart.addLegendBox(LegendBoxBuilders.HorizontalLegendBox).add(chart);

    return () => {
      chart.dispose();
    };
  }, []);

  // done thnx
  return (
    <div className="graph-container">
      <div id="currency-graph" className="graph-container"></div>
    </div>
  );
};

export default TopCurrencyGraph;


Your code looks syntax wise correct, but I believe you are running into issues due to not managing asynchronous code (axios getting data from your endpoint) properly.您的代码看起来语法正确,但我相信您会遇到问题,因为您没有正确管理异步代码(axios 从您的端点获取数据)。

const map: { [name: string]: graphPoint[] } = {};
axios
   .get(historicalAddr)
   .then((res) => {
      // This code is NOT executed immediately, but only after some time later.
      ...
   })

// This code and everything below is executed BEFORE the code inside `then` block.
// Because of this, you end up supplying `undefined` or other incorrect values to series / charts which shows as errors.
const chart = lightningChart().ChartXY({
   theme: Themes.lightNew,
   container: "currency-graph",
});

You might find it useful to debug the values you supply to series, for example like below.您可能会发现调试您提供给系列的值很有用,例如如下所示。 I think the values are not what you would expect.我认为这些值不是您所期望的。

seriesArray.forEach((series, idx) => {
   if (idx === 1) {
      console.log('series.add', lists[idx])
      series.add(lists[idx]);
   }
});

Improvement suggestion改进建议

Here's my attempt at modifying the code you supplied to manage the asynchronous data loading correctly, by moving all code that relies on the data after the data is processed.这是我尝试修改您提供的代码以正确管理异步数据加载,方法是在处理数据后移动所有依赖于数据的代码。

/* eslint-disable new-cap */
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable no-magic-numbers */
import React, { useEffect, useState } from "react";
import { LegendBoxBuilders, lightningChart, Themes } from "@arction/lcjs";
import "./TopCurrencyGraph.css";
import axios from "axios";
export interface data {
  data: dataPoint[];
}

export interface dataPoint {
  currency: string;
  percentage: number;
  timestamp: string;
}

interface graphPoint {
  x: number;
  y: number;
}

const TopCurrencyGraph = () => {
  const historicalAddr = `http://${
    process.env.back || "localhost:8000"
  }/historical24hChangeData`;

  useEffect(() => {
    const chart = lightningChart().ChartXY({
      theme: Themes.lightNew,
      container: "currency-graph",
    });
    chart.setTitle("Top Currencies");
    chart.getDefaultAxisX().setTitle("Time");
    chart.getDefaultAxisY().setTitle("Percentage Change");

    const seriesArray = new Array(5).fill(null).map((_, idx) =>
      chart
        .addLineSeries({
          dataPattern: {
            pattern: "ProgressiveX",
          },
        })
        // eslint-disable-next-line arrow-parens
        .setStrokeStyle((stroke) => stroke.setThickness(1))
    );

    chart.addLegendBox(LegendBoxBuilders.HorizontalLegendBox).add(chart);

    axios
      .get(historicalAddr)
      .then((res) => {
        const { points } = res.data;
        const pointList = points as dataPoint[];
        const map: { [name: string]: graphPoint[] } = {};
        pointList.forEach((obj) => {
          const newPoint = {
            x: new Date(obj.timestamp).getTime() * (60 * 24),
            y: obj.percentage * 100,
          };
          if (obj.currency in map) {
            map[obj.currency].push(newPoint);
          } else {
            map[obj.currency] = [newPoint];
          }
        });

        const entries = Object.entries(map);
        const names = entries.map(([a, _b]) => a);
        const lists = entries.map(([_, b]) => b);

        seriesArray.forEach((series, idx) => {
          series.setName(names[idx])
          if (idx === 1) {
            series.add(lists[idx]);
          }
        });
      })
      .catch((err) => {
        console.log(err, historicalAddr);
      });

    return () => {
      chart.dispose();
    };
  }, []);

  // done thnx
  return (
    <div className="graph-container">
      <div id="currency-graph" className="graph-container"></div>
    </div>
  );
};

export default TopCurrencyGraph;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM