Some important points that I would like to cover here before answering your question are as follows:
We can easily do asynchronous calls within useEffect() hook.
The call-back function within useEffect() cannot be async, so callback cannot use async-await
, because useEffect() cannot return a promise
which every async function
does by default:
useEffect(async ()=>{
})
// This will return error and will not work
So we can set async
function inside the callback function or outside in our component.
Now coming to your question:
useEffect(() => {
setTimeout(() => {
setSomeState(complexComputation(someDependency));
}, 0);
}, [someDependency]);
The main point here is that our useEffect() hook will run initially, and setTimeout() function is simply passed to the Web-API
of Browser, Timer
starts normally and only once all the code is executed on the call-stack
, the callback within setTimeout gets executed.
Check running the below code.
useEffect(() => {
console.log("Line one")
setTimeout(() => {
setSomeState(complexComputation(someDependency));
console.log("line two");
}, 3000);
console.log("Line three");
}, [someDependency]);
Output will be:
Line one
Line Three
Line two // after all other synchronous consoles are executed :)
The question is not about, "what running of useEffect() asynchronously or synchronously mean"
, but about in what scenarios does useEffect() run first, which runs in both the scenarios.
And since in your code you as using the second argument and passing the value (a state). i-e.,
useEffect(()=>{},[someDependency])
Whenever someDependency
again the component re-renders and our useEffect()
is again invoked and the code (asynchronous or synchronous) gets executed.