我正在构建一个用 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;
您的
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 [];
}
};