Home > Mobile >  API Data undefined in react
API Data undefined in react

Time:06-18

So I'm super new to react. I have some code where I use fetch to get data from an API (that I created, structured like {'userData': {'overall': {'rank': '10', 'level': '99', 'xp': '200000000'}}}) and I display it on screen. It was working fine for hours and now all of a sudden without touching any code, it's broken. it will display the data just fine if i make an API request and then refresh the page. but then when I refresh the page again it tells me "Uncaught TypeError: Cannot read properties of undefined (reading 'overall')" I don't know what I'm doing wrong and I'm wondering if someone can help me because I don't know how it became undefined, it was reading it just fine and then on refresh it changes to undefined. here's my code for the component

import { useEffect, useState } from 'react';

function Activities() {
    let name = "three-dawg";
    function fetchPlayerData(name){
        fetch('http://127.0.0.1:8000/player='   name   '?format=json')
            .then(response => response.json())
            .then(data => setPlayerData(data));
    };

    function refreshPage() {
        window.location.reload(false)
    }

    const [playerData, setPlayerData] = useState([]);
    useEffect(() => {fetchPlayerData(name)}, [name]);

    return (
        <div>
            Hello {playerData._id}
            <button onClick={() => {
                fetchPlayerData(name)
                refreshPage()
            }}>load player</button>
            <ul>
               <li>{playerData.userData.overall.rank}</li>
            </ul>
        </div>
    );
}

export default Activities;

CodePudding user response:

Ok there is an easy fix to this problem. Just add "?" after all the data you are fetching.

 return (
    <div>
        Hello {playerData?._id}
        <button onClick={() => {
            fetchPlayerData(name)
            refreshPage()
        }}>load player</button>
        <ul>
           <li>{playerData?.userData.overall.rank}</li>
        </ul>
    </div>
);

The data fetching is asynchronous so, when you render the screen it renders initial state at first which is an empty array. It takes time for data to be fetched. So, by adding a question mark, the renderer checks if the data is present and only then renders your component.

CodePudding user response:

const [playerData, setPlayerData] = useState([]);

Your initial state is an empty array, so that's the value you will have on your first render. Arrays don't have a userData property, so you get an exception when you try to access playerData.userData.overall.

You either need to make your initial data look like your real data, so that playerData.userData.overall.rank is valid, or, more likely, you need to add code to check if you still have the initial data and render something different while waiting for the load to complete. null or undefined would be easier to check for, so you might want to use one of those as the initial state.

const [playerData, setPlayerData] = useState(null);
useEffect(() => {fetchPlayerData(name)}, [name]);

if (!playerData) {
  return <div>Loading...</div>
}

return (
  <div>
   // ...the rest of your code
  </div>
)

You also probably want to remove the code that reloads the page.

  • Related