仅在React中返回承诺后,我才能绘制图表吗?

问题描述

我正在为Chartjs使用React包装器。我使用fetch API调用Nomics API来获取数据并将其存储在某些arrays中。然后,我想在新的Chartjs实例中使用数组。除了渲染我的图表外,其他所有东西都起作用,我认为这是因为它是在诺言完成之前渲染的。我该如何只返回图表,直到对Nomics API的调用完成,或者在完成后对其进行更新?

这是我的组件:

import React from 'react';
import {Line} from 'react-chartjs-2';

const Day = () =>{
    
    //starting price reiterated over the length of the data.
    const zeroLine = [];
    //stores all the increments of time
    const timeLabels = [];
    //List of all of the prices
    const prices = [];
    
    
    
    fetch("https://api.nomics.com/v1/currencies/sparkline?key=yadayadayada&ids=BTC&start=2020-04-14T00%3A00%3A00Z&end=2020-04-20T01%3A00%3A00Z",{}).then((res) => res.json())
      .then((result) => {
        
        for(var i = 0; i <= result[0].prices.length - 1; i++){
            zeroLine.push(result[0].prices[0]);
            timeLabels.push(result[0].timestamps[i]);
            prices.push(result[0].prices[i]);
            
        }
      });
    
    const chartData = {
      labels: timeLabels,datasets: [
        {
          label: 'Price',fill: false,lineTension: 0,backgroundColor: 'rgba(75,192,1)',borderColor: 'rgba(0,borderWidth: 2,data: prices
        },{
          //Change this to create points for every time/date
          label: '0 line',borderDash: [10,5],data: zeroLine,}
      ]
    }

    return(
    <Line
          data={chartData}
          options={{
            elements:{
                point: {
                    radius: 0
                }
            },title:{
              display:true,text:'BTC Price',fontSize:20
            },legend:{
              display:false,position:'right'
            }
          }}
        />
    )
}

export default Day;

解决方法

您可以使用useStateuseEffect钩子来实现此目的。

useEffect钩子可以用作componentDidMount(当您将依赖项数组作为[]传递时),componentDidUpdate(当您将值传递给依赖项数组时)和componentWillUnmount(当您具有第三个函数时)

另一方面,useState与使用setState相似。每当它更改时,都会触发组件重新渲染。

在您的情况下,我们现在要做的基本上是在获取响应时更新状态,这会触发重新渲染

import React,{useState,useEffect} from 'react';
import {Line} from 'react-chartjs-2';

const Day = () =>{
    const [zeroLine,setZeroLine] = useState([]);
    const [timeLabels,setTimeLabels] = useState([]);
    const [prices,setPrices] = useState([]);
    
    useEffect(() => {
      fetch("https://api.nomics.com/v1/currencies/sparkline?key=yadayadayada&ids=BTC&start=2020-04-14T00%3A00%3A00Z&end=2020-04-20T01%3A00%3A00Z",{}).then((res) => res.json())
      .then((result) => {
        const zL = [];
        const tL = [];
        const p = [];
        for(var i = 0; i <= result[0].prices.length - 1; i++){
            zL.push(result[0].prices[0]);
            tL.push(result[0].timestamps[i]);
            p.push(result[0].prices[i]);
        }
        setZeroLine(zL);
        setTimeLabels(tL);
        setPrices(p);
      });
    },[]);
    
    const chartData = {
      labels: timeLabels,datasets: [
        {
          label: 'Price',fill: false,lineTension: 0,backgroundColor: 'rgba(75,192,1)',borderColor: 'rgba(0,borderWidth: 2,data: prices
        },{
          //Change this to create points for every time/date
          label: '0 line',borderDash: [10,5],data: zeroLine,}
      ]
    }

    return(
      <Line
          data={chartData}
          options={{
            elements:{
                point: {
                    radius: 0
                }
            },title:{
              display:true,text:'BTC Price',fontSize:20
            },legend:{
              display:false,position:'right'
            }
          }}
        />
    )
}

export default Day;

,

您可以使用useStateuseEffect钩子以及条件渲染来做到这一点:

import React,useEffect} from 'react';
import {Line} from 'react-chartjs-2';

const Day = () =>{
    // this piece of state will hold the data passed to the chart component once it returns from your fetch call.
    const [chartData,setChartData] = useState(null);
    
    
    const getChartData = () => fetch("https://api.nomics.com/v1/currencies/sparkline?key=yadayadayada&ids=BTC&start=2020-04-14T00%3A00%3A00Z&end=2020-04-20T01%3A00%3A00Z",{}).then((res) => res.json())
      .then((result) => {
            
        //starting price reiterated over the length of the data.
        const zeroLine = [];
        //stores all the increments of time
        const timeLabels = [];
        //List of all of the prices
        const prices = [];
        for(var i = 0; i <= result[0].prices.length - 1; i++){
            zeroLine.push(result[0].prices[0]);
            timeLabels.push(result[0].timestamps[i]);
            prices.push(result[0].prices[i]);
            
        }
        const chartData = {
          labels: timeLabels,datasets: [
            {
              label: 'Price',data: prices
            },{
              //Change this to create points for every time/date
              label: '0 line',}
          ]
        }
        setChartData(chartData)
      });

    useEffect(getChartData,[])

    return chartData ? (
    <Line
          data={chartData}
          options={{
            elements:{
                point: {
                    radius: 0
                }
            },position:'right'
            }
          }}
        />
    ) : <p>loading...</p>
}

export default Day;