skip to Main Content

I am building a guessing game built wtih react and "artsy.api". The guessing game can be accessed through my index page by clicking a button.

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

Whenever I press the button to navigate to the guessing game page, the page becomes un responsive and only displayes "Guess the Artist" and directly underneath "Loading…". I cant even right click and inspect the page to check for the errors in the console.

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;

Can someone suggest a solution to ammends the code or a different approach to solving the problem?

Ive attempted to add a debounce function to limit the number of API calls, as this is the only aspect that i think could be casuing the problem but it hasnt seemed to solve the problem.

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;

2

Answers


  1. Chosen as BEST ANSWER

    I fetch the artist directly in the getRandomArtists function instead of using the artistLink.

    Solution:

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

  2. You have an infinite loop in your code in the getRandomArtists() function:

    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);
          }
        }
    

    the condition in the while loop never became false because _embedded.artists.length most of the time is 1 so randomArtists will always contains one element because you check !randomArtists.includes(randomArtist) and this will be always false

    I hope you understand the logic 🙂

    Solution:

    you can get artists directly from the 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 [];
        }
      };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search