Search code examples
reactjsapiapollouse-effect

useEffect calling API on page load errors


I'm working on a project that utilizes the IGDB to display information about various video game titles. I've got an API call on the search page that returns the information appropriately. Upon clicking on one of those titles from the search, I load a new page with detailed information about the game. The API call for the detailed information is the exact same as the one for the search functionality (exception being that they retrieve different fields from the DB, aside from that, exactly the same) and both return the data appropriately and in the exact same format (an array of objects.) However, I have had a lot of trouble displaying the data on the game details page.

Here is the response that I am having trouble displaying:

Detailed API response

And, just for the sake of as much detail for you guys as possible, here is the successfully displayed response from the search page:

enter image description here

The way I have it set up is to run a useEffect hook on page load. The hook does run, and the data is returned, but displaying the data has been a challenge. Here is the current hook.

    useEffect(() => {

        async function getGameId(gameId) {

            const response = await getSpecificGame(gameId);

            if (!response.ok) {
                throw new Error('Something went wrong...');
            }

            const result = response.json();

            const gameData = result?.map((game) => ({

                gameId: game.id,
                name: game.name,
                cover: game.cover,
                summary: game.summary,
                platforms: game.platforms,
                genres: game.genres,
                
            }));

            setSelectedGame(gameData);
        }

        getGameId(gameId);
        
    }, [])

With this code I receive the following error:

Uncaught (in promise) TypeError: result.map is not a function

With the error being with result.map, I'm very lost on where to go from here. I have wondered if perhaps the response.json() line is unnecessary or misplaced, but with the data returning in the exact same fashion as it does for the search page, I'm not sure what I would need to change. The error is not thrown on the response, meaning the data comes back ok, but it is thrown on the result.map() line, meaning either the result = response.json() is somehow incorrect/unnecessary, or I'm missing another line that needs to be there. This confuses me greatly though, since the other API call I make to perform the search works and is set up the same way. For extra context, I will post the properly functioning API call from the search page as well, this one is within a form handler:

    const handleFormSubmit = async (event) => {
        event.preventDefault();

        if (!searchInput) {
            return false;
        }

        try {
            

            const response = await getGame(searchInput);

            if (!response.ok) {
                throw new Error('Something went wrong...');
            }

            const result = await response.json();

            const gameData = result.map((game) => ({
                
                gameId: game.id,
                name: game.name,
                cover: game.cover,
            }));

            setSearchedGames(gameData);
            setSearchInput('');
        } catch (err) {
            console.error(err);
        }
    };

Here are the API calls that go with those functions.

export const getGame = (searchInput) => {
    return fetch(`https://id.twitch.tv/oauth2/token?client_id=************&client_secret=****************&grant_type=client_credentials`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        }
    })
        .then(response => response.json())
        .then(data => {
            const accessToken = data.access_token;


            return fetch(`https://fathomless-river-46653.herokuapp.com/https://api.igdb.com/v4/games/`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Client-ID': '***********',
                    'Authorization': `Bearer ${accessToken}`
                },
                body: `
                search "${searchInput}";
                fields name,cover.url;`
            })
        });
};

export const getSpecificGame = (gameId) => {
    return fetch(`https://id.twitch.tv/oauth2/token?client_id=************&client_secret=**************&grant_type=client_credentials`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        }
    })
        .then(response => response.json())
        .then(data => {
            const accessToken = data.access_token;


            return fetch(`https://fathomless-river-46653.herokuapp.com/https://api.igdb.com/v4/games/`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Client-ID': '**************',
                    'Authorization': `Bearer ${accessToken}`
                },
                body: `
                fields name,summary,platforms.name,genres.name,cover.url;
                where id = ${gameId};`
            })
        });
}

This seems to be a simple matter of appropriately changing the syntax to function with useEffect instead of a form handler, but it is proving to be quite the challenge. I've looked over probably 20 threads of similar issues, but none of which have been able to solve my problem.

I've wondered if I should go another route entirely, completely removing the useEffect hook and trying something else, but this feels like a learning opportunity on how to make use of useEffect so I'm trying my best to get this working.

I would be happy to attach any extra code to assist with an answer. I posted a very similar question yesterday and received some helpful responses, but since then have made progress and reached another roadblock point. Thank you in advance to anyone who is able to assist!


Solution

  • const result = response.json();
    

    There is a small error here, you need to await it:

    const result = await response.json();
    

    In the other example you posted from a form handler, it's awaited correctly, so it works.