0

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

function Activities() {
    let name = "three-dawg";
    function fetchPlayerData(name){
        fetch(URL)
            .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>
    );
}
3
  • are you trying to load the data initially when the page loads ? Commented Jun 17, 2022 at 16:37
  • There should be no need for window.location.reload(false) in a React app. And you're not changing the name variable anywhere so that useEffect is redundant. You may want useEffect(() => ... []) with an empty dependency array instead. FYI code rarely stops working. What did you change? Commented Jun 17, 2022 at 16:40
  • Hi guys. I didn't change anything. I'm gonna end up using that name variable in there later to take in text and use that text to make the API call so that's why the name data is there. It works initially, and then stops working when I refresh the page Commented Jun 17, 2022 at 16:44

2 Answers 2

1
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.

Sign up to request clarification or add additional context in comments.

4 Comments

the code that reloads the page is there because later on i want to add a text field where you enter in the player name and on button click it refreshes the page and displays that data, it only refreshes the page if you click the button
Understood, but that doesn't require reloading the page, just fetching new data and setting state
ahh okay. sorry like i said im super new to react
For me this didn't work, because the data variable (the respective playerData in this example here) was an empty object, and thus it was neither null nor undefined. I had to check if it had no keys like so: if (Object.keys(data).length == 0) { ......} I hope this helps somehow...
0

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.

2 Comments

Tried that and it worked the first time but then when i refresh the page it just tells me overall is undefined still
just keep on adding question marks to everything that is undefined. That's one way to solve it. Or may be console log the data and see if the overall spelling is same on both sides.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.