subprimeloads
subprimeloads

Reputation: 392

Rendering a Chart in React with Asynchronous Object Data

I'm attempting make a chart with data that is being fetched from an API, but a problem i'm having is that i've been unable to properly render the chart due to an asynchronous call im making for the data. I believe the chart is executing before the data can be filled because upon loading the window nothing renders. However when I tried hard coding values in place of 'timestamps' and 'prices' in the data variable, the chart immediately renders. Does anyone know how I can format the rest of the code so that the chart renders only after the timestamp and price arrays have been filled?

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

const MarketAPI = require('market-api');
const Client = new MarketAPI();

function GRAPH(){

  const timestamps = [];
  const prices = [];

  var getData = async() => {

    const fromTS = (Date.now() / 1000 | 0 ) - 86400; // 1D from current timestamp
    const toTS = Date.now() / 1000 | 0; // current timestamp

    let get = await Client.assets.fetchAssetHist('MSFT', {
      from: fromTS,
      to: toTS,
    });

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

    console.log(timestamps);
    console.log(prices);
  }

  const data =  {

    labels: timestamps,
    datasets: [
      {
        data: prices,
        fill: true,
        backgroundColor: 'rgba(243, 230, 200, 0.2)', 
        borderColor: 'rgba(243, 210, 18)', 
      },
    ],
  };

  const options = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: {
      legend: {
        display: false
      }
    },
    scales: {
      x: {
        grid: {
          display: false
        },
        display:true
      },
      y: {
        grid: {
          display: false
        },
        display: false
      }
    },
    elements: {
      point:{
          radius: 0
      }
    },
  };

  useEffect(()=>{

    getData()

  },[]);

  return(
    <div>

      <Line data={data} options={options}/>

    </div>
  );
}

function App() {
  return (

      <GRAPH/>
  );
}

Upvotes: 1

Views: 810

Answers (1)

Nishanth
Nishanth

Reputation: 354

Use the useState Hook to store your data instead.

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

const MarketAPI = require('market-api');
const Client = new MarketAPI();

function GRAPH(){

  const timestamps = [];
  const prices = [];
  const [data, setData] = useState({})
  var getData = async() => {
    
    const fromTS = (Date.now() / 1000 | 0 ) - 86400; // 1D from current timestamp
    const toTS = Date.now() / 1000 | 0; // current timestamp

    let get = await Client.assets.fetchAssetHist('MSFT', {
      from: fromTS,
      to: toTS,
    });

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

    console.log(timestamps);
    console.log(prices);
  }

  setData({

    labels: timestamps,
    datasets: [
      {
        data: prices,
        fill: true,
        backgroundColor: 'rgba(243, 230, 200, 0.2)', 
        borderColor: 'rgba(243, 210, 18)', 
      },
    ],
  })
  

  const options = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: {
      legend: {
        display: false
      }
    },
    scales: {
      x: {
        grid: {
          display: false
        },
        display:true
      },
      y: {
        grid: {
          display: false
        },
        display: false
      }
    },
    elements: {
      point:{
          radius: 0
      }
    },
  };

  useEffect(()=>{

    getData()

  },[]);

  return(
    <div>

      <Line data={data} options={options}/>

    </div>
  );
}

function App() {
  return (

      <GRAPH/>
  );
}

Upvotes: 1

Related Questions