Reactdom.render (); reactdom.render (); UpdateContainer () – > updateContainerAtExpirationTime () – > scheduleRootUpdate () – > createUpdate ()

Update (setState()); Update (setState()); Update (setState()

Source:

export const UpdateState = 0;

export const ReplaceState = 1;

export const ForceUpdate = 2;

export const CaptureUpdate = 3;



export function createUpdate(

  expirationTime: ExpirationTime,

  suspenseConfig: null | SuspenseConfig,

) :Update< * >
{

  return {

    // Update expiration time

    expirationTime,

    suspenseConfig,



    // export const UpdateState = 0;

    // export const ReplaceState = 1;

    // export const ForceUpdate = 2;

    // export const CaptureUpdate = 3;



    // Focus on CaptureUpdate, an ErrorBoundaries function after React16

    // If an error occurs during rendering, you can update the page by selecting a new render state (indicating an error state)

    tag: UpdateState, Update 1 replace 2 Force update 3 Capture update



    // Update the content, such as the first argument received by setState

    payload: null.



    // Corresponding callback, such as setState({}, callback)

    callback: null.



    // Points to the next update

    next: null.



    // Point to next side effect

    nextEffect: null.

  };

}

Copy the code

(1) When the value of the tag is CaptureUpdate, it is a trap update. (2) When the value of the tag is CaptureUpdate, it is a trap update. (3) When the value of the tag is CaptureUpdate, it is a trap update

(2) Multiple updates are pushed into the update queue, and the next attribute points to the next node

Reactdom.render (); reactDom.render (); UpdateContainer () – > updateContainerAtExpirationTime () – > scheduleRootUpdate () – > enqueueUpdate (current, The update) – > createUpdateQueue ()

Function: Performs internal updates in sequence

Source:

// Create an update queue

export function createUpdateQueue<State> (baseState: State) :UpdateQueue<State{

  const queue: UpdateQueue<State> = {

    // Apply the updated state

    baseState,

    // The first update in the queue

    firstUpdate: null.

    // Last update in the queue

    lastUpdate: null.

    // The first catch type of UPDATE in the queue

    firstCapturedUpdate: null.

    // The last update of the catch type in the queue

    lastCapturedUpdate: null.

    // First side effect

    firstEffect: null.

    // Last side effect

    lastEffect: null.

    firstCapturedEffectnull.

    lastCapturedEffectnull.

  };

  return queue;

}

Copy the code

(1) After the setState component is set, baseState renders and updates the state, and the next update takes the updated state

(2) The update between firstUpdate and lastUpdate is concatenated by next of the previous update

EnqueueUpdate () is used as a one-way list to store updates, and next is used as a series of updates

Source:

// Every time setState is updated, every time updateQueue is updated

/ / the current fiber

export function enqueueUpdate<State> (fiber: Fiber, update: Update<State>{

  // Update queues are created lazily.

  / / alternate workInProgress namely

  / / fiber that is current



  // There is a mapping between current and alternate

  // Make sure that current and workInProgress updateQueue are consistent

  const alternate = fiber.alternate;

  / / the current queue

  let queue1;

  / / alternate queue

  let queue2;

  // If alternate is null

  if (alternate === null) {

    // There's only one fiber.

    queue1 = fiber.updateQueue;

    queue2 = null;

    // If Queue1 is still empty, initialize the update queue

    if (queue1 === null) {

      queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);

    }

  } else {

    // There are two owners.

    // If alternate is not empty, the respective update queue is taken

    queue1 = fiber.updateQueue;

    queue2 = alternate.updateQueue;

    if (queue1 === null) {

      if (queue2 === null) {

        // Neither fiber has an update queue. Create new ones.

        / / initialization

        queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);

        queue2 = alternate.updateQueue = createUpdateQueue(

          alternate.memoizedState,

        );

      } else {

        // Only one fiber has an update queue. Clone to create a new one.

        // If queue2 exists but queue1 does not, copy Queue1 based on Queue2

        queue1 = fiber.updateQueue = cloneUpdateQueue(queue2);

      }

    } else {

      if (queue2 === null) {

        // Only one fiber has an update queue. Clone to create a new one.

        queue2 = alternate.updateQueue = cloneUpdateQueue(queue1);

      } else {

        // Both owners have an update queue.

      }

    }

  }

  if (queue2 === null || queue1 === queue2) {

    // There's only a single queue.

    // Put the update into Queue1

    appendUpdateToQueue(queue1, update);

  } else {

    // There are two queues. We need to append the update to both queues,

    // While accounting for the persistent structure of the list -- we don't

    // want the same update to be added multiple times.

    // React does not want to queue the same update multiple times

    // If both queues are empty, add update

    if (queue1.lastUpdate === null || queue2.lastUpdate === null) {

      // One of the queues is not empty. We must add the update to both queues.

      appendUpdateToQueue(queue1, update);

      appendUpdateToQueue(queue2, update);

    }

    // If neither queue is empty, only update is added to Queue1 because both structures are shared

    // In queue2, point lastUpdate to update

    else {

      // Both queues are non-empty. The last update is the same in both lists,

      // because of structural sharing. So, only append to one of the lists.

      appendUpdateToQueue(queue1, update);

      // But we still need to update the `lastUpdate` pointer of queue2.

      queue2.lastUpdate = update;

    }

  }

}

Copy the code

Queue1 = fiber. UpdateQueue; queue1 = fiber. Queue2 takes alternate. UpdateQueue(2) If both are null, createUpdateQueue() gets the initial queue. Call cloneUpdateQueue() to get the queue (4) from the other party. If neither is null, update is treated as lastUpdate


(after)