【问题标题】:React: Chartjs won't show data from Flask backendReact:Chartjs 不会显示来自 Flask 后端的数据
【发布时间】:2022-10-15 03:02:13
【问题描述】:

我已经构建了一个使用 Flask 后端和 React 前端的 Web 应用程序,我对 React 很陌生,所以我的知识有限。我想将两个数据列表从后端传递到前端,然后使用 Chartjs 显示它们。

前端接收数据,显示图表但未填充数据。

显示的输出如下所示:


1,2,3,4,5,6

没有数据的图表


烧瓶应用程序:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/api", methods=['GET'])
def get_data():
    return jsonify({"y": [1, 2, 3, 2, 3, 4],             
                    "x": [1, 2, 3, 4, 5, 6],
                    }
                   )

反应前端:

import React, { useState, useEffect } from "react";
import Chart from "chart.js";


export default function CardLineChart() {
  const [x, setX] = useState([]);
  const [y, setY] = useState([]);

  useEffect(() => {
    fetch('/api')
      .then(res => res.json())
      .then(data => {
        setY(data.y);
        setX(data.x);
    });
    
    let config = {
      type: "line",
      data: {
        labels: X,
        datasets: [
          {
            label: new Date().getFullYear(),
            backgroundColor: "rgb(252,228,0,0.7)",
            borderColor: "rgb(252,228,0,0.9)",
            data: Y,
          },
        ],
      },
      options: {
        maintainAspectRatio: false,
        responsive: true,
        title: {
          display: false,
          text: "Orders Chart",
        },
        tooltips: {
          mode: "index",
          intersect: false,
        },
        hover: {
          mode: "nearest",
          intersect: true,
        },
        scales: {

          xAxes: [
            {
              display: false,
              scaleLabel: {
                display: false,
                labelString: "Month",
              },
              gridLines: {
                display: false,
                color: "rgba(0, 0, 0, 0)",
                zeroLineColor: "rgba(0, 0, 0, 0)",
              },
            },
          ],

          yAxes: [
            {
              display: true,
              scaleLabel: {
                display: false,
                labelString: "Value",
              },
              ticks: {
                suggestedMin: 0,
              },
              gridLines: {
                drawBorder: false,
                lineWidth: 0.4,
                color: "rgba(33, 37, 41, 0.2)",
                zeroLineColor: "rgba(33, 37, 41, 0.15)",
              },
            },
          ],
        },
      },
    };
    var ctx = document.getElementById("line-chart").getContext("2d");
    window.myLine = new Chart(ctx, config);
  }, []);
  return (
    <>
      <p>{x}</p>
      <div className="relative flex flex-col min-w-0 break-words bg-white w-full mb-4 rounded">
        <div className="p-4 flex-auto">
          {/* Chart */}
          <div className="relative h-250-px">
            <canvas id="line-chart"></canvas>
          </div>
        </div>
      </div>
    </>
  );
}

【问题讨论】:

    标签: javascript reactjs flask


    【解决方案1】:

    这段代码打破了一些基本的 React 规则。

    首先,在编写 React 组件时直接操作 DOM 时,警报器应该响起。 99.9% 的时间有更好的方法。首选refs 而不是document.getElementById("line-chart")。

    window.myLine = new Chart(ctx, config); 也是不好的做法。这打破了 React,将数据全局粘贴在窗口上,这几乎可以肯定是一种 hack。不清楚为什么window.line 被认为是必要的,但如果组件树中的其他地方需要图表,请考虑提升状态,使用 reducer 或上下文,而不是绕过 React。

    其次,setState 和fetch 不是同步的。尽管使用X(大写)而不是x(小写),这种模式总是会失败:

    () => {
      fetch('/api/').then(data => {
        setX(data.x);
        setY(data.y);
        // executes last
      );
    
      // trying to use use x and y here will fail
    })();
    

    在fetch 承诺有机会在then 块中解析之前,任何代替注释行的代码都将同步执行。此外,状态设置也是异步的,因此存在双重打击(如果大写拼写错误算数,则为三重打击)。这种模式也是错误的:

    () => {
      setX(data.x); // state setting is async, executes last
      setY(data.y);
    
      // trying to use use x and y here will fail
    })();
    

    这是一个简单的演示,您可以根据自己的用例进行调整。一个可能更好的设计是保持在父组件中获取数据并将图表移动到有条件地呈现的子组件,避免引用和额外效果。

    const {useEffect, useRef, useState} = React;
    
    // Mocks for demonstration
    class Chart {
      constructor(canvas, {x, y}) {
        canvas.getContext("2d")
          .fillText(`${x[0]} ${y[0]}`, 40, 40);
      }
    }
    fetch = () => Promise.resolve({
      json: () => Promise.resolve({x: [42], y: [1]})
    });
    //
    
    const CardLineChart = () => {
      const [x, setX] = useState([]);
      const [y, setY] = useState([]);
      const [chart, setChart] = useState(null);
      const canvas = useRef(null);
    
      useEffect(() => {
        fetch("/api")
          .then(res => res.json())
          .then(data => {
            setX(data.x);
            setY(data.y);
          });
      }, []);
    
      useEffect(() => {
        if (x.length && y.length) {
          const config = {x, y};
          setChart(new Chart(canvas.current, config));
        }
      }, [x, y]);
    
      return (
        <canvas ref={canvas}></canvas>
      );
    };
    
    ReactDOM.createRoot(document.querySelector("#app"))
      .render(<CardLineChart />);
    <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <div id="app"></div>

    【讨论】:

      猜你喜欢
      • 2020-05-25
      • 2021-10-26
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      • 1970-01-01
      相关资源
      最近更新 更多