如何从API获取数据并在网页无响应的情况下显示?

问题描述 投票:0回答:1

我正在构建一个用 React 和“artsy.api”构建的猜谜游戏。单击按钮即可通过我的索引页面访问猜谜游戏。

<Link to="/guessing-game">
  {" "}
  {/* Link to Guessing Game page */}
  <Button type="primary">Play Guessing Game</Button>{" "}
  {/* Button to navigate to Guessing Game page */}
</Link>          

每当我按下按钮导航到猜谜游戏页面时,该页面就会变得无响应,并且仅显示“猜猜艺术家”并直接位于“正在加载...”下方。我什至无法右键单击并检查页面以检查控制台中的错误。

GuessingsGame.tsx:

import React, { useState, useEffect } from "react";
import axios from "axios"; // Import Axios
import "./GuessingGame.css";

interface Artwork {
  _embedded: {
    artists: { name: string }[];
  };
  _links: {
    thumbnail: { href: string };
    artists: { href: string };
  };
  title: string;
}

const GuessingGame: React.FC = () => {
  const [artwork, setArtwork] = useState<Artwork | null>(null);
  const [options, setOptions] = useState<string[]>([]);
  const [selectedOption, setSelectedOption] = useState<string | null>(null);
  const [score, setScore] = useState<number>(0);
  const [loading, setLoading] = useState<boolean>(true);

  useEffect(() => {
    const fetchArtworkData = async () => {
      try {
        const response = await axios.get("https://api.artsy.net/api/artworks", {
          headers: {
            "X-XAPP-Token":
              "My_API_KEY",
          },
        });
        const { _embedded } = response.data;
        if (_embedded && _embedded.artworks && _embedded.artworks.length > 0) {
          const randomArtwork: Artwork =
            _embedded.artworks[
              Math.floor(Math.random() * _embedded.artworks.length)
            ];
          setArtwork(randomArtwork);
          const randomArtists = await getRandomArtists(
            randomArtwork._links.artists.href
          );
          const correctArtist = randomArtwork._embedded.artists[0].name;
          setOptions([...randomArtists, correctArtist]);
          setLoading(false);
        }
      } catch (error) {
        console.error("Error fetching artwork data:", error);
        setLoading(false);
      }
    };

    fetchArtworkData();
  }, []);

  const getRandomArtists = async (artistsLink: string): Promise<string[]> => {
    try {
      const response = await axios.get(artistsLink, {
        headers: {
          "X-XAPP-Token":
            "My_API_KEY",
        },
      });
      const { _embedded } = response.data;
      if (_embedded && _embedded.artists) {
        const randomArtists: string[] = [];
        while (randomArtists.length < 3) {
          const randomIndex = Math.floor(
            Math.random() * _embedded.artists.length
          );
          const randomArtist = _embedded.artists[randomIndex].name;
          if (!randomArtists.includes(randomArtist)) {
            randomArtists.push(randomArtist);
          }
        }
        return randomArtists;
      }
    } catch (error) {
      console.error("Error fetching artists:", error);
    }
    return [];
  };

  const handleOptionSelect = (option: string) => {
    setSelectedOption(option);
    if (option === artwork?._embedded.artists[0].name) {
      setScore(score + 1);
    }
  };

  return (
    <div className="guessing-game-container">
      <h1>Guess the Artist</h1>
      {loading ? (
        <p>Loading...</p>
      ) : artwork ? (
        <div>
          <img
            src={artwork._links.thumbnail.href}
            alt={artwork.title}
            className="artwork-thumbnail"
          />
          <h2>{artwork.title}</h2>
          <h3>Options:</h3>
          <div className="options-container">
            {options.map((option, index) => (
              <button
                key={index}
                onClick={() => handleOptionSelect(option)}
                className={`option-button ${
                  selectedOption === option ? "selected" : ""
                }`}
              >
                {option}
              </button>
            ))}
          </div>
          <p>Score: {score}</p>
        </div>
      ) : (
        <p>No artwork available</p>
      )}
    </div>
  );
};

export default GuessingGame;

有人可以提出修改代码的解决方案或解决问题的不同方法吗?

我尝试添加一个去抖函数来限制API调用的数量,因为这是我认为可能导致问题的唯一方面,但它似乎并没有解决问题。

import React, { useState, useEffect } from "react";
import "./GuessingGame.css";

interface Artwork {
  _embedded: {
    artists: { name: string }[];
  };
  _links: {
    thumbnail: { href: string };
    artists: { href: string };
  };
  title: string;
}

const GuessingGame: React.FC = () => {
  const [artwork, setArtwork] = useState<Artwork | null>(null);
  const [options, setOptions] = useState<string[]>([]);
  const [selectedOption, setSelectedOption] = useState<string | null>(null);
  const [score, setScore] = useState<number>(0);
  const [loading, setLoading] = useState<boolean>(true);

  useEffect(() => {
    const fetchArtworkData = async () => {
      try {
        const response = await fetch("https://api.artsy.net/api/artworks", {
          headers: {
            "X-XAPP-Token":
              "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6IiIsInN1YmplY3RfYXBwbGljYXRpb24iOiIzMDU2MDk0Yi05ODUwLTRjYTktOTJiNy05MWM4MWYwZTYyNDYiLCJleHAiOjE3MTUzMzQ0MDUsImlhdCI6MTcxNDcyOTYwNSwiYXVkIjoiMzA1NjA5NGItOTg1MC00Y2E5LTkyYjctOTFjODFmMGU2MjQ2IiwiaXNzIjoiR3Jhdml0eSIsImp0aSI6IjY2MzRiMjg1MTc0YmUxMDAxMmRiNDc2ZSJ9.hGIPQb-W4jHjitTo5KGWguRo0YpRqlUNIAQlKJpaDl8",
          },
        });
        const { _embedded } = await response.json();
        if (_embedded && _embedded.artworks && _embedded.artworks.length > 0) {
          const randomArtwork: Artwork =
            _embedded.artworks[
              Math.floor(Math.random() * _embedded.artworks.length)
            ];
          setArtwork(randomArtwork);
          const randomArtists = await getRandomArtists(
            randomArtwork._links.artists.href
          );
          const correctArtist = randomArtwork._embedded.artists[0].name;
          setOptions([...randomArtists, correctArtist]);
          setLoading(false);
        }
      } catch (error) {
        console.error("Error fetching artwork data:", error);
        setLoading(false);
      }
    };

    fetchArtworkData();
  }, []);

  const getRandomArtists = async (artistsLink: string): Promise<string[]> => {
    try {
      const response = await fetch(artistsLink, {
        headers: {
          "X-XAPP-Token":
            "eyJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6IiIsInN1YmplY3RfYXBwbGljYXRpb24iOiIzMDU2MDk0Yi05ODUwLTRjYTktOTJiNy05MWM4MWYwZTYyNDYiLCJleHAiOjE3MTUzMzQ0MDUsImlhdCI6MTcxNDcyOTYwNSwiYXVkIjoiMzA1NjA5NGItOTg1MC00Y2E5LTkyYjctOTFjODFmMGU2MjQ2IiwiaXNzIjoiR3Jhdml0eSIsImp0aSI6IjY2MzRiMjg1MTc0YmUxMDAxMmRiNDc2ZSJ9.hGIPQb-W4jHjitTo5KGWguRo0YpRqlUNIAQlKJpaDl8",
        },
      });
      const { _embedded } = await response.json();
      if (_embedded && _embedded.artists) {
        const randomArtists: string[] = [];
        while (randomArtists.length < 3) {
          const randomIndex = Math.floor(
            Math.random() * _embedded.artists.length
          );
          const randomArtist = _embedded.artists[randomIndex].name;
          if (!randomArtists.includes(randomArtist)) {
            randomArtists.push(randomArtist);
          }
        }
        return randomArtists; // Add return statement here
      }
    } catch (error) {
      console.error("Error fetching artists:", error);
    }
    return []; // Add return statement here to handle other cases
  };

  const handleOptionSelect = (option: string) => {
    setSelectedOption(option);
    if (option === artwork?._embedded.artists[0].name) {
      setScore(score + 1);
    }
  };

  return (
    <div className="guessing-game-container">
      <h1>Guess the Artist</h1>
      {loading ? (
        <p>Loading...</p>
      ) : artwork ? (
        <div>
          <img
            src={artwork._links.thumbnail.href}
            alt={artwork.title}
            className="artwork-thumbnail"
          />
          <h2>{artwork.title}</h2>
          <h3>Options:</h3>
          <div className="options-container">
            {options.map((option, index) => (
              <button
                key={index}
                onClick={() => handleOptionSelect(option)}
                className={`option-button ${
                  selectedOption === option ? "selected" : ""
                }`}
              >
                {option}
              </button>
            ))}
          </div>
          <p>Score: {score}</p>
        </div>
      ) : (
        <p>No artwork available</p>
      )}
    </div>
  );
};

export default GuessingGame;

css reactjs typescript api react-hooks
1个回答
0
投票

您的

getRandomArtists()
函数中的代码有无限循环:

while (randomArtists.length < 3) {
      const randomIndex = Math.floor(
        Math.random() * _embedded.artists.length
      );
      const randomArtist = _embedded.artists[randomIndex].name;
      if (!randomArtists.includes(randomArtist)) {
        randomArtists.push(randomArtist);
      }
    }

while 循环中的条件永远不会变为 false,因为

_embedded.artists.length
大多数时候都是 1,所以
randomArtists
将始终包含一个元素,因为您检查
!randomArtists.includes(randomArtist)
并且这将始终为 false

我希望你能理解其中的逻辑:)

解决方案:

您可以直接从API获取艺术家:

  const getRandomArtists = async (): Promise<string[]> => {
    try {
      const response = await axios.get('https://api.artsy.net/api/artists', {
        headers: {
          'X-XAPP-Token': 'token',
        },
      });

      return response.data._embedded.artists;
    } catch (error) {
      console.error('Error fetching artists:', error);
      return [];
    }
  };
© www.soinside.com 2019 - 2024. All rights reserved.