I’m probably missing something super obvious here, but I’m tearing my hear out trying to figure out why react sometimes is able to recognize data that I fetched while other other times it totally can’t. This usually happens after I either refresh the browser or turn off the localhost server and then restart. Anyone know what this happens?
Below is my code. Note that sometimes this renders perfectly, other times react will ways the "p" variable is undefined and therefore can not map, even though I don’t make a single change to the code and the data still loads ok on console log: Why does this happen?
import React, {useState, useEffect} from 'react'
import axios from './db.js'
function App() {
const [p, setP] = useState()
const getParameters= async(req, res)=>{
const response = await axios.get('/getTable/myData')
const data = response.data;
console.log(data) // <--this always works.
setP(data)
}
useEffect(()=>{
getParameters()
},[])
return (
<div className="App">
{p.map(row=>( // <---This is hit or miss. React sometimes sees it.
<div>
{row.label}
</div>
))
}
</div>
);
}
export default App;
4
Answers
Posting because I don’t have enough reputation to comment…
You should use conditional rendering before you access p.map(…) because your state p could be undefined, given that you’re doing an asynchronous request that may or may not be finished by the time you’re rendering your component.
You can achieve conditional rendering by simply checking if your state p is not undefined before accessing it. F.e.: {p && p.map(…)}
You should change your code at two lines:
and
for null safety
First approach, I think you can use the async & await inside the useEffect to make sure your data gets loaded first.
Another option, react does not allow you to fetch immediately after you setState due to virtual DOM. You can also check on that.
Another option, You can always check if the data is loaded or not using
Because, you’re not passing anything to the
useState
hook, the value ofp
isundefined
initally.Note that
useEffect
"runs after render", meaning the JSX will be be returned. In the first render,p
is stillundefined
and has no.map
method, leading to a runtime error.Then after the first render, the
useEffect
runs andgetParameters
is called in whichsetP(data)
triggers a re-render.In this following render,
p
is now the array of data and can be mapped over in the JSX.You can fix this by checking if
p
is defined and an array before mapping over it.And note that each child in a list should have a unique "key" prop. See Rendering Lists in the React docs.