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