React triggers updates in five different ways:

ReactDOM.render
this.setState
this.forceUpdate
useState
useReducer
Copy the code

UseState (mountState) is the useReducer(mountReducer) whose reducer parameter is basicStateReducer (basicStateReducer).

So useState and useReducer actually call the same updateReducer method when updating

HooksDispatcherOnUpdateInDEV = {
  useReducer: function (reducer, initialArg, init) {
     return updateReducer(reducer, initialArg, init);
  },
  useState: function (initialState) {
    returnupdateState(initialState); }},function updateState(initialState) {
  return updateReducer(basicStateReducer);
}
Copy the code

So, after learning the update process of useState, you will know the update process of useReducer.

Let’s get started.

const App = () => { const [a, setA] = useState(1); return ( <> <div onClick={() => { setA(1); setA(2); setA(3); }}>{a}</div> {/* Ignore other useless code */} </>)}Copy the code

When clicked, setData is set three times, and the whole process looks something like this:

setA --> dispatch (dispatchAction) --> scheduleUpdateOnFiber --> ensureRootIsScheduled --> ... Scheduled... --> performSyncWorkOnRoot --> ... -> beginWork --> updateFunctionComponent --> updateFunctionComponent --> renderWithHooks --> Component --> updateReducer -- >...Copy the code

One of the methods setA goes through each time is:

setA --> dispatch (dispatchAction) --> scheduleUpdateOnFiber --> ensureRootIsScheduled --> ... Scheduled...Copy the code

After dispatching, when the render phase starts, the three setA have been executed and the data is saved in the hook. Queue, you can see dispatchAction:

function dispatchAction<S.A> (fiber: Fiber, queue: UpdateQueue
       
        , action: A,
       ,>) {
  // Ignore irrelevant code
  const pending = queue.pending;
  if (pending === null) {
    // This is the first update. Create a circular list.
    update.next = update;
  } else {
    update.next = pending.next;
    pending.next = update;
  }
  queue.pending = update;
}
Copy the code

Note the assignment of the mountReducer or mountState queue and the dispatchAction parameter:

const queue = (hook.queue = {
  // ...
});

const dispatch: Dispatch<
    BasicStateAction<S>,
  > = (queue.dispatch = (dispatchAction.bind(
    null,
    currentlyRenderingFiber,
    queue,
  ): any));
Copy the code

Update is stored on hook. Queue.

RenderWithHooks () {Component function (); Component useState ();}

if(current ! = =null&& current.memoizedState ! = =null) {
  ReactCurrentDispatcher$1.current = HooksDispatcherOnUpdateInDEV;
}
Copy the code

Call the updateReducer method to update the hook value. Next, we update fiber on the commitMutation of the COMMIT phase. Finally, we switch the current tree and the workInProgress tree to display the update on the screen.

Reference:

updateState

mountState

basicStateReducer

mountReducer

HooksDispatcherOnUpdateInDEV

[dispatchAction](