Home > OS >  Reloading the page loses API data using useContext
Reloading the page loses API data using useContext

Time:10-30

I am using a RapidAPI Api to load crypto currency data in my project. The data is loading and even rendering in my React components but as soon as I refresh, I have to load the data from the beginning to get to specific coin data. On reload, I get TypeError: Cannot read properties of undefined (reading 'name')

Here is my code:

import React, { useState, useEffect } from "react";
import "./Homepage.css";
import CryptoCard from "../Card/Card";
import axios from "axios";

const Homepage = () => {
  const [coinData, setCoinData] = useState([]);

  useEffect(() => {
    const i = 5;
    const options = {
      method: "GET",
      url: "https://coinranking1.p.rapidapi.com/exchanges",
      headers: {
        "x-rapidapi-host": "coinranking1.p.rapidapi.com",
        "x-rapidapi-key": "REDACTED",
      },
    };

    axios
      .request(options)
      .then((response) => {
        setCoinData(response.data.data.exchanges);
        // console.log(coinData);
        // console.log("Working!!");
      })
      .catch((error) => {
        console.error(error);
      });
  }, []);

  return (
    <div className="homepage">
      <div className="heading">
        <h1>Discover {coinData[0].name}</h1>
        <hr className="line" />
      </div>
      <div className="cards-container">
        <CryptoCard />
      </div>
    </div>
  );
};

export default Homepage;

Why am I getting

CodePudding user response:

Reason for your error message

coinData[0] does not exist when rendering the component initially. You've defined it as useState([]), so every time the component gets created, you start with a fresh empty array. Therefore, you should add a check, if you got some data in it.

<h1>Discover {coinData.length > 0 && coinData[0].name}</h1>

Reason for refetch

Your useEffect will be executed once when the component gets rendered. You make the request and put the data in the coinData state. But the state is not persistent. You could use the local storage to cache your request across page refresh. To do this, you need to persist the data when your request finishes and load the data when you create your state.


const [coinData, setCoinData] = useState([], () => {
        const localData = localStorage.getItem('coinData');
        return localData ? JSON.parse(localData) : [];
    });

useEffect(() => {
    const i = 5;
    const options = {
      method: "GET",
      url: "https://coinranking1.p.rapidapi.com/exchanges",
      headers: {
        "x-rapidapi-host": "coinranking1.p.rapidapi.com",
        "x-rapidapi-key": "REDACTED",
      },
    };

    axios
      .request(options)
      .then((response) => {
        setCoinData(response.data.data.exchanges);
        // console.log(coinData);
        // console.log("Working!!");

        // persist in localStorage
        localStorage.setItem("coinData", JSON.stringify(response.data.data.exchanges))
      })
      .catch((error) => {
        console.error(error);
      });
  }, []);

EDIT: This will still make a request every time you hit refresh, but I guess this code will make it clear how it works. So I guess you'll be able to add an if-condition, if you got some data already and skip the new request ;-)

  • Related