In React design, setState is divided into two phases: update creation and update execution.

Create updates: setState first creates an update and enlists the update to the current fiber.updateQueue. A task is then scheduled (scheduleSyncCallback or scheduleCallback) in ensureRootIsSchuled.

Update: sometime in the future (calling setState function have been performed at this time) to perform the first stage (performSyncWorkOnRoot or performConcurrentWorkOnRoot) schedule tasks.

Update data structure and enqueue process

Multiple calls to setState create a list on currentFiber, with pending pointing to the last node of the list and pending.next pointing to the first node. So update Value is actually a link, so it’s easy to find the header.

export type Update<State> = {
  // TODO: Temporary field. Will remove this by storing a map of
  // transition -> event time on the root.
  eventTime: number,
  lane: Lane,

  tag: 0 | 1 | 2 | 3.// UpdateState | ReplaceState | ForceUpdate | CaptureUpdate 
  payload: any, // setState the first argument
  callback: (() = > mixed) | null.// setState the second argument

  next: Update<State> | null};Copy the code
const pending = sharedQueue.pending;
if (pending === null) {
  // This is the first update. Create a circular list.
  update.next = update;
} else {
  update.next = pending.next;
  pending.next = update;
}
sharedQueue.pending = update;
Copy the code

A way to make setState look like synchronization

setStateAsync(state) {
  return new Promise((resolve) = > {
    this.setState(state, resolve)
  });
}

async onClick() {
  await this.setStateAsync({count: 0})
  console.log(this.state.count)
}
Copy the code

An implementation quirk of Class Components can also synchronize setState

handleClick = () = > {
  setTimeout(() = > {
    this.setState(({ count }) = > ({ count: count + 1 }));

    // { count: 1, flag: false }
    console.log(this.state);

    this.setState(({ flag }) = > ({ flag: !flag }));
  });
};
Copy the code

Until React 18, we only batched updates during the React event handlers. Updates inside of promises, setTimeout, native event handlers, or any other event were not batched in React by default.

Before React 18, React only made bulk updates to setState written in React Event Handlers. Not for setState written in Promises, setTimeout, Native Event Handlers, or other events

The original link