【问题标题】:Reloading the page loses API data using useContext使用 useContext 重新加载页面会丢失 API 数据
【发布时间】:2021-12-14 20:42:27
【问题描述】:

我正在使用 RapidAPI Api 在我的项目中加载加密货币数据。数据正在我的 React 组件中加载甚至呈现,但是一旦我刷新,我必须从头开始加载数据以获取特定的硬币数据。重新加载时,我得到 TypeError: Cannot read properties of undefined (reading 'name')

这是我的代码:

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;

我为什么会得到

【问题讨论】:

  • 是的,上下文数据不会在页面加载之间持续存在。为什么会这样?
  • 检查coinData 数组应该可以解决这个问题:&lt;h1&gt;Discover {coinData[0]?.name}&lt;/h1&gt;
  • 顺便说一句,你的标题是错误的,你不使用 useContext,只是 useState ;-)
  • 哦,我是想写useEffect!我的错!

标签: reactjs api react-hooks


【解决方案1】:

错误消息的原因

coinData[0] 在最初渲染组件时不存在。您已将其定义为useState([]),因此每次创建组件时,您都会从一个新的空数组开始。因此,如果您有一些数据,您应该添加一个检查。

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

重新获取的原因

您的useEffect 将在组件渲染时执行一次。您提出请求并将数据置于coinData 状态。但是状态不是持久的。您可以使用本地存储在页面刷新期间缓存您的请求。为此,您需要在请求完成时保留数据,并在创建状态时加载数据。


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);
      });
  }, []);

编辑:这仍然会在您每次点击刷新时发出请求,但我想这段代码会清楚地说明它是如何工作的。所以我想你可以添加一个 if 条件,如果你已经有一些数据并跳过新请求;-)

【讨论】:

  • Discover {coinData[0]?.name}

    无需对 useEffect 或本地存储进行任何编辑,它的工作原理相同。
  • 但是您的解决方案更加完整和安全。谢谢大佬!
  • 感谢您的反馈,很高兴看到人们仍然接受答案并且不放弃解决方案。谢谢人
猜你喜欢
  • 1970-01-01
  • 2015-11-09
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多