This is the 15th day of my participation in the More text Challenge. For more details, see more text Challenge

background

We know that React’s setState method does not execute synchronously. The multiple setState changes that occur during the React lifecycle are combined to reduce the number of DOM changes pushed to the browser, thereby improving front-end performance. So how does this work?

  1. Event handlers come with batchedUpdates
  2. There are no batchedUpdates in setTimeout
  3. Active batchedUpdates

1 species:

Batch update will print 0, 0, 0, and then the button text will be displayed as 1. Each setState goes through enqueueUpdate (create the update and join the queue) -> scheduleWork (find the corresponding FiberRoot node) -> requestWork (put FiberRoot node) ), but the context variable isBatchingUpdates is marked true somewhere outside, so this time setState goes along the way, Has not yet reached the next performSyncWork or scheduleCakkbackWithExpirationTime began to return all the way out of the stack.

The isBatchingUpdates variable is marked to true in the old call stack (the event handler we bind to onClick is wrapped in multiple layers by react), and then fn(a, b) goes through a series of three setState operations inside, Finally isBatchingUpdates returns to false and performSyncWork is performed.

The second:

SetTimeout (() => {this.countNumber()}, 0), Again, add goes through interactiveUpdates 1 context, which also executes setTimeout, and then fn(a,b) is done, because ultimately the browser calls the callback to setTimeout and then executes this.countNumber inside, In the context of interactiveUpdates1, it also executes setTimeout, and then fn(a, b) is done, because ultimately the browser calls the callback to setTimeout and executes this.countNumber inside, In the context of interactiveUpdates1, it also executes setTimeout, and then fn(a,b) is done, because ultimately the browser calls the callback to setTimeout and executes this.countNumber inside, InteractiveUpdates1 continues to execute its performSyncWork and is done. Obviously, no matter what sync updates performSyncWork does, our setState hasn’t been executed yet. Then wait until the setTimeout callback is idle, and then the setState is executed. There is no batch update. So each setState will execute the performSyncWork in the requestWork separately until the render is complete without interruption, and 3 setstates will update the entire render 3 times (this is not good performance, so you don’t usually react this way).

What does it mean to update the render synchronously without interruption? If you look at the output in the demo, each time it prints out the innerText of the latest button DOM.

Third:

As you can guess, the first batch update context was “missed” by using setTimeout, and another batch update context was created when the setTimeout callback was executed.

function App() {
   const [a, setA] = useState(0);
   
   function add() {
       setTimeout(() = > {
           console.log('run 4');
           setA(a + 3);
           console.log('run 5');
           setA(a + 8);
           console.log('run 6');
       });
       console.log('run 1');
       setA(a + 1);
       console.log('run 2');
       setA(a + 1);
       console.log('run 3');
   }
   console.log('trigger');
   return (
       <Fragment>
           <div onClick={add}>{a}</div>
       </Fragment>)}Copy the code