Home > Net >  Where does the function continue after a re-render?
Where does the function continue after a re-render?

Time:09-30

When the state called loading is set to true and a re-render of the component is caused, where does the function continue? Does it run console.log(1) again, just that it's that fast that I can't track it? Or does it contiune with console.log(2)? Or is the re-render happening after console.log(2) while the asynchronous operation is running? The same question appears regarding the moment loading is set to false again. Will it re-render after console.log(3) and console.log(4) have run or between those as the order in the code would suppose?

If there was no async operation running between the state changes, would the Spinner even appear at some point?, or would the entire function run before it re-renders and therby the state true not even trigger a re-render, because the state changes get "bundled" which would mean that it would only re-render when the state is set to false again?

Sorry for the complicated formulation but I don't know any other way to express myself. I struggle with the idea that a re-render means that the entire functional component is re-run, because a function call could thereby be interrupted. I just don't undestand how and where it conitunes and if that is consistent, because it should be IMO.

´´´ export default function IndexComponent() {

const [loading, setLoading] = useState(false)

const doSomething = async () => {
    console.log(1)
    setLoading(true) //re-renders and Spinner appears
    console.log(2)
    await new Promise(resolve => setTimeout(resolve, 5000));
    console.log(3)
    setLoading(false)//re-renders and Spinner disappears
    console.log(4)
}


return (
    <div>
        <button onClick={doSomething}>Login</button>
        {loading && <div>Spinner</div>}
    </div>
)

} ´´´

CodePudding user response:

You may be over-thinking this. There's no magic happening in React which in any way changes how JavaScript works. When a function is invoked, it executes. Nothing in React interrupts that function in any way. And a re-render does indeed re-invoke the component function.

So in this case, every time the button is clicked, doSomething is invoked and executes all of the logic therein.

What may be confusing you regarding re-renders in this specific case is the fact that doSomething is asynchronous and is not awaited. So after this executes:

setLoading(true)

A state update has been queued. It won't be processed until the thread is free to process asynchronous operations. That can happen here:

await new Promise(resolve => setTimeout(resolve, 5000));

It depends on whether the function itself is being awaited too. And in the code shown it isn't. So this operation puts another asynchronous operation on the queue, and frees up control to start processing the asynchronous operations already in place. Which, in this case, is a state update and a re-render.

Then when the above Promise resolves, the remaining operations in the function are processed. Which also includes a state update, which triggers a re-render.


Alternatively, suppose you didn't have anything asynchronous happening. Suppose you just did this:

console.log(1)
setLoading(true)
console.log(2)
setLoading(false)
console.log(3)

In this case only one re-render is (potentially) triggered. Multiple state updates are made, but states updates are asynchronous and batched. So they're all waiting until the thread is available, and then the batch of updates are processed. In this case the net result of those updates is no change, so there may be no re-render.

CodePudding user response:

I hope i understood your questions correctly. A call to setState is also asynchon and the changes are getting batched for performance gains. So your doSomething function probably runs to the end before the state Changes take effect.

Here is the respective Article in the React Docs: https://reactjs.org/docs/faq-state.html#what-does-setstate-do

  • Related