Reputation: 106
I have a fetch
inside of a useEffect
hook. I'm console logging at different parts within it and getting some strange results
const [name, setName] = useState("Placeholder Name");
const [lat, setLat] = useState("Placeholder Lat");
const [long, setLong] = useState("Placeholder Long");
const [counter, setCounter] = useState(0);
const [loading, setLoading] = useState(true);
useEffect(() => {
console.log("top level");
fetch("https://api.wheretheiss.at/v1/satellites/25544")
.then(res => res.json())
.then(data => {
console.log("inside fetch", name, long, lat);
setName(data.name);
setLat(data.latitude);
setLong(data.longitude);
setLoading(false);
});
});
// Result on mount
top level
inside fetch Placeholder Name Placeholder Long Placeholder Lat
top level
top level
top level
top level
inside fetch iss Placeholder Long Placeholder Lat
inside fetch iss 71.768808134445 27.26618722337
top level
top level
inside fetch iss 71.815373509259 27.312786482746
When the component mounts, I understand that the useEffect
will run whenever a state value updates. There is a 1 second limit on that API endpoint so the effect will stop running when its current value matches the returned value.
My specific confusion is why "top level" is being logged 4 times in a row before the "fetch" console log is called. This may have to do with the asynchronous fetch, but I'm hoping someone could clarify.
Upvotes: 2
Views: 68
Reputation: 12174
Since react hooks doesn't batch state updates by default, here's a step by step explanation of the behaviour:
top level // initial render
inside fetch Placeholder Name Placeholder Long Placeholder Lat // prior to re-render
top level // re-render: from setName()
top level // re-render: from setLat()
top level // re-render: from setLong()
top level // re-render: from setLoading()
inside fetch iss Placeholder Long Placeholder Lat // name updated
// The lines below could run infinitely every time long, lat changes
inside fetch iss 71.768808134445 27.26618722337 // long, lat updated
top level // re-render: new value for lat - setLat()
top level // re-render: new value for long - setLong()
inside fetch iss 71.815373509259 27.312786482746 // long, lat updated
Upvotes: 1
Reputation: 1939
Every time you set state with one of the useState callbacks the component re renders.
You are setting a state value 4 times in a row so the component re renders 4 time in a row very quickly. Every time it renders it is calling your useEffect hook because you don’t have an array of dependencies. So it’s console.logging 4 times in a row because the rest of the function is async
Upvotes: 1