Search code examples
javascriptarraysreactjsjsonfetch

React/Javascript - TypeError: Cannot read properties of undefined (reading 'json')


React & Javascript noob here, I'm trying to build my first React project. What I want to do is to have a button that fetches automatically the last matches I played on a game. I'm using a API that, when called correctly, returns this json:

{data: 
       [{id: 0, internal_id: "_map_id_halo1_pillar_of_autumn", name: "The Pillar Of Autumn"},
…]}

I want to extract the name for each object of data and display an unordered list below the button.

But when I click the button, the browser displays the error:

TypeError: Cannot read properties of undefined (reading 'json')

The code that does what I mentioned is as follows:

async fetchHaloMaps()
    {
        const url = 'https://cryptum.halodotapi.com/games/hmcc/metadata/maps'
        const mapNames = [];

        fetch(url, {
            "method": 'GET',
            "headers": {
                        'Content-Type': 'application/json',
                        'Cryptum-API-Version': '2.3-alpha',
                        'Authorization': 'Cryptum-Token XXX'
                     }
        })
        .then(response => {
            console.log(response);
            if (!response.ok)
                throw new Error("Response not ok!");
        })
        .then(response => 
            response.json())
        .then(data => {
                    
            const i=0;
             for (const d of data)
            {
                mapNames[i] = d.name;
                i++;
            }

            this.setState((state, props) => ({
                numberOfMaps : i
            }));
        })  
        .catch(error => {
            console.log("There was an error: " + error);
        });
    }

I think I'm "parsing" the JSON in the wrong way. But in the JSON, data i indeed an array with a "name" attribute. So I wanted to cycle the data array and copy the attribute "name", but the code above is not working. I know the HTTP request with fetch does succeed, since in the console.log I can see the response object and it has the 200 OK field, and I can see the JSON associated with the browser developer tools.


Solution

  • You did not return anything from this .then:

        .then(response => {
            console.log(response);
            if (!response.ok)
                throw new Error("Response not ok!");
        })
    

    so there is no value that gets passed along to the next .then.

    While you could do return response, a better approach would be to remove the intermediate .then entirely - only insert a .then when you need to wait for something asynchronous. At the time you get the response, you can check if it's OK and then return the .json(), without waiting in between.

    .then(response => {
        if (!response.ok) {
            throw new Error("Response not ok!");
        }
        return response.json();
    })
    .then(data => {