繁体   English   中英

将 API 数据推送到 Chart.js

[英]Pushing API Data into Chart.js

我试图将我的 API 数据推送到我的图表中,但数据更新时间与图表呈现时间似乎存在问题。 我正在控制台记录我的两个 arrays,它没有在数组中显示任何内容。 有谁知道我需要更改什么才能将我的数据更新到 state,然后再使用该数据呈现图表?

function SmallBox(props) {
    const [chartNums, setChartNums] = useState([])
    const [chartLabels, setChartLabels] = useState([])
    const [chartData, setChartData] = useState({})
    const x = [];
    const y = [];

    const fetchData = async () => {
      await fetch(`https://api.coingecko.com/api/v3/coins/${props.id}/market_chart?vs_currency=usd&days=1`)
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        for (let i = 0; i < data.prices.length; i++){
          x.push(data.prices[i][0])
          setChartLabels(x)
        }

        for (let i = 0; i < data.prices.length; i++){
          y.push(data.prices[i][1])
          setChartNums(y)
        }
        
      })
    };

    const chart = async () => {
        await fetchData()
        console.log(chartNums)
        console.log(chartLabels)
        
        setChartData({
            labels: chartLabels,
            datasets: [
                {
                    label: '$',
                    data: chartNums,
                    backgroundColor: ['rgba(0,0,0,0.09)'],
                    borderColor: `${props.color}`,
                    borderWidth: 4,
                    borderJoinStyle: 'round',
                    borderCapStyle: 'round',
                    borderWidth: 3,
                    pointRadius: 0,
                    pointHitRadius: 10,
                    lineTension: .2,
                }
            ]
        })
    }

    useEffect(() =>{
      chart();
    }, []);

    return (
        <div id={props.id} className="smallBox">
            <div className="smallBox_info">
                <img className="smallBox-icon" src={props.image} alt={props.symbol}/>
                <h2>{props.title}</h2>
            </div>
            
            <div className="smallBox_numbers">
                <h2 className="smallBox-price">$ {props.currentPrice}</h2>
                <h5 className="smallBox-roc">{props.percentChange}</h5>
            </div>
            
            <div className="smallBox_graph">
                <Line data={chartData} options={{
                    responsive: true,
                    maintainAspectRatio: false,
                    title: {text: 'ThickBoyz', display: false},
                    legend: {display: false},
                    layout: {
                        padding: {
                          left: 0,
                          right: 0,
                          top: 0,
                          bottom: 0
                        }
                      },
                      scales: {
                        xAxes: [{
                          display: false,
                          gridLines: {}
                        }],
                        yAxes: [{
                          display: false,
                          gridLines: {}
                        }]
                      },
                      tooltips: {
                        callbacks: {
                          //This removes the tooltip title
                          title: function() {}
                       },
                        //this removes legend color
                        displayColors: false,
                        yPadding: 10,
                        xPadding: 10,
                        position: 'nearest',
                        caretSize: 10,
                        backgroundColor: 'rgba(255,255,255,.9)',
                        bodyFontSize: 15,
                        bodyFontColor: '#303030' 
                      }
                    }}/>  
            </div>
        </div>
    )
}

export default SmallBox

正确使用 async-await,不要将 promise then 方法与 await 混合使用。

import React, { useEffect, useState, useCallback } from "react";
import { Line } from "react-chartjs-2";
import "./styles.css";

export default function App() {
  const [chartNums, setChartNums] = useState([]);
  const [chartLabels, setChartLabels] = useState([]);
  const [chartData, setChartData] = useState({});
  const x = [];
  const y = [];
  const props = {
    id: "bitcoin"
  };

  const fetchData = useCallback(async () => {
    const response = await fetch(
      `https://api.coingecko.com/api/v3/coins/${props.id}/market_chart?vs_currency=usd&days=1`
    );
    const data = await response.json();
    if (data && data.prices) {
      console.log(data.prices);
      for (let i = 0; i < data.prices.length; i++) {
        x.push(data.prices[i][0]);
        setChartLabels(x);
      }

      for (let i = 0; i < data.prices.length; i++) {
        y.push(data.prices[i][1]);
        setChartNums(y);
      }
    }
  }, [props]);

  const chart = useCallback(async () => {
    await fetchData();
    console.log(chartNums);
    console.log(chartLabels);

    setChartData({
      labels: chartLabels,
      datasets: [
        {
          label: "$",
          data: chartNums,
          backgroundColor: ["rgba(0,0,0,0.09)"],
          borderColor: `${props.color}`,
          borderWidth: 4,
          borderJoinStyle: "round",
          borderCapStyle: "round",
          pointRadius: 0,
          pointHitRadius: 10,
          lineTension: 0.2
        }
      ]
    });
  }, [chartNums, chartLabels, fetchData, props.color]);

  useEffect(() => {
    chart();
  }, [chart]);

  return (
    <div id={props.id} className="smallBox">
      <div className="smallBox_info">
        <img className="smallBox-icon" src={props.image} alt={props.symbol} />
        <h2>{props.title}</h2>
      </div>

      <div className="smallBox_numbers">
        <h2 className="smallBox-price">$ {props.currentPrice}</h2>
        <h5 className="smallBox-roc">{props.percentChange}</h5>
      </div>

      <div className="smallBox_graph">
        <Line
          data={chartData}
          options={{
            responsive: true,
            maintainAspectRatio: false,
            title: { text: "ThickBoyz", display: false },
            legend: { display: false },
            layout: {
              padding: {
                left: 0,
                right: 0,
                top: 0,
                bottom: 0
              }
            },
            scales: {
              xAxes: [
                {
                  display: false,
                  gridLines: {}
                }
              ],
              yAxes: [
                {
                  display: false,
                  gridLines: {}
                }
              ]
            },
            tooltips: {
              callbacks: {
                //This removes the tooltip title
                title: function () {}
              },
              //this removes legend color
              displayColors: false,
              yPadding: 10,
              xPadding: 10,
              position: "nearest",
              caretSize: 10,
              backgroundColor: "rgba(255,255,255,.9)",
              bodyFontSize: 15,
              bodyFontColor: "#303030"
            }
          }}
        />
      </div>
    </div>
  );
}

沙盒链接 - https://codesandbox.io/s/chartjs-fetchapidata-r3ghc?file=/src/App.js

考虑坚持使用.then()语法或async/await 我建议使用后者,这应该使事情更简单:

 const fetchData = async () => {
      const response = await fetch(`https://api.coingecko.com/api/v3/coins/1/market_chart?vs_currency=usd&days=1`)
      const data = await response.json()
      data.prices.forEach(price => {
        x.push(price[0])
        setChartLabels(x)
        
        y.push(price[1])
        setChartNums(y)
    });
}

接下来,考虑您是否真的需要将chartLabelschartNums存储在 React state 中——它们没有在您的 JSX 中使用,因此将它们作为普通的旧变量返回可能更清楚:

 const fetchData = async () => {
      const response = await fetch(`https://api.coingecko.com/api/v3/coins/1/market_chart?vs_currency=usd&days=1`)
      const data = await response.json()
      chartLabels = data.prices.map(price => price[0])
      chartNums = data.prices.map(price => price[1]
      return [chartLabels,chartNums]
}

然后后来,

const [chartLabels, chartNums] = await fetchData()
  const [chartLabels, setChartLabels] = useState([]);
  const [chartData, setChartData] = useState({});
  const x = [];
  const y = [];
  const props = {
    id: "bitcoin"
  };

  const fetchData = useCallback(async () => {
    const response = await fetch(
      `https://api.coingecko.com/api/v3/coins/${props.id}/market_chart?vs_currency=usd&days=1`
    );
    const data = await response.json();
    if (data && data.prices) {
      console.log(data.prices);
      for (let i = 0; i < data.prices.length; i++) {
        x.push(data.prices[i][0]);
        setChartLabels(x);
      }

      for (let i = 0; i < data.prices.length; i++) {
        y.push(data.prices[i][1]);
        setChartNums(y);
      }
    }
  }, [props,x,y]);

参考上面提供的解决方案,您可以初始化 x 和 y arrays 包装 useMemo Hook 以返回更优化的解决方案并防止这样的警告

专业提示:如果您不正确地添加依赖项或根本没有添加依赖项,重复的 API 调用可能会让您被阻止。

暂无
暂无

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

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