【问题标题】:Lightning JS Chart causing crashes and not showing data correctly闪电 JS 图表导致崩溃并且无法正确显示数据
【发布时间】:2022-01-05 00:31:54
【问题描述】:

我有一个组件,我想显示一个图表,其中包含表示过去 24 小时内价格变化的多条线系列。我有一个发送此数据的端点,我使用下面的代码来显示它。

其中一个问题来自似乎来自库本身的错误,这意味着图表甚至不会显示。 Errors from the console when I load the page.

其他时候,页面会加载一秒钟然后变白并消耗足够的 CPU 导致崩溃。

图表实际显示在屏幕上的几次,在取消注释第 81-85 行之前它不会显示任何线条,然后它会显示线条但不会放大它们,从而在屏幕上留下一团糟。

任何帮助将不胜感激。

/* 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;


【问题讨论】:

    标签: reactjs typescript lightningchart


    【解决方案1】:

    您的代码看起来语法正确,但我相信您遇到了问题,因为没有正确管理异步代码(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",
    });
    

    您可能会发现调试您提供给系列的值很有用,例如如下所示。我认为这些值不是您所期望的。

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

    改进建议

    这是我修改您提供的代码以正确管理异步数据加载的尝试,方法是在处理数据后移动所有依赖于数据的代码。

    /* 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;
    

    【讨论】:

    • 成功了,非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 2021-02-21
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多