ReactFiberUpdateQueue

insertUpdateIntoFiber

It takes fiber element and update object and create queues by calling ensureUpdateQueuesand set update info into queues by insertUpdateIntoQueue. update object which is generated here will look like this.

const update = {
  expirationTime,
  partialState: {element},
  callback,
  isReplace: false,
  isForced: false,
  capturedValue: null,
  next: null,
};

https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberUpdateQueue.js#L147

let q1;
let q2;

export function insertUpdateIntoFiber<State>(
  fiber: Fiber,
  update: Update<State>,
): void {
  ensureUpdateQueues(fiber);
  const queue1: Fiber = (q1: any);
  const queue2: Fiber | null = (q2: any);

  // If there's only one queue, add the update to that queue and exit.
  if (queue2 === null) {
    insertUpdateIntoQueue(queue1, update);
    return;
  }

  // If either queue is empty, we need to add to both queues.
  if (queue1.last === null || queue2.last === null) {
    insertUpdateIntoQueue(queue1, update);
    insertUpdateIntoQueue(queue2, update);
    return;
  }

  // If both lists are not empty, the last update is the same for both lists
  // because of structural sharing. So, we should only append to one of
  // the lists.
  insertUpdateIntoQueue(queue1, update);
  // But we still need to update the `last` pointer of queue2.
  queue2.last = update;
}

ensureUpdateQueues

https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberUpdateQueue.js#L118

This function is invoked from insertUpdateIntoFiberfunction. This generates queues by calling createUpdateQueue and assigns them to q1 and q2.

export function ensureUpdateQueues(fiber: Fiber) {
  q1 = q2 = null;
  // We'll have at least one and at most two distinct update queues.
  const alternateFiber = fiber.alternate;
  let queue1 = fiber.updateQueue;
  if (queue1 === null) {
    // TODO: We don't know what the base state will be until we begin work.
    // It depends on which fiber is the next current. Initialize with an empty
    // base state, then set to the memoizedState when rendering. Not super
    // happy with this approach.
    queue1 = fiber.updateQueue = createUpdateQueue((null: any));
  }

  let queue2;
  if (alternateFiber !== null) {
    queue2 = alternateFiber.updateQueue;
    if (queue2 === null) {
      queue2 = alternateFiber.updateQueue = createUpdateQueue((null: any));
    }
  } else {
    queue2 = null;
  }
  queue2 = queue2 !== queue1 ? queue2 : null;

  // Use module variables instead of returning a tuple
  q1 = queue1;
  q2 = queue2;
}

createUpdateQueue

https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberUpdateQueue.js#L79

Singly linked-list of updates. When an update is scheduled, it is added to the queue of the current fiber and the work-in-progress fiber. The two queues are separate but they share a persistent structure. During reconciliation, updates are removed from the work-in-progress fiber, but they remain on the current fiber. That ensures that if a work-in-progress is aborted, the aborted updates are recovered by cloning from current. The work-in-progress queue is always a subset of the current queue. When the tree is committed, the work-in-progress becomes the current.

function createUpdateQueue<State>(baseState: State): UpdateQueue<State> {
  const queue: UpdateQueue<State> = {
    baseState,
    expirationTime: NoWork,
    first: null,
    last: null,
    callbackList: null,
    hasForceUpdate: false,
    isInitialized: false,
    capturedValues: null,
  };

  return queue;
}

insertUpdateIntoQueue

https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiberUpdateQueue.js\#L96


export function insertUpdateIntoQueue<State>(
  queue: UpdateQueue<State>,
  update: Update<State>,
): void {
  // Append the update to the end of the list.
  if (queue.last === null) {
    // Queue is empty
    queue.first = queue.last = update;
  } else {
    queue.last.next = update;
    queue.last = update;
  }
  if (
    queue.expirationTime === NoWork ||
    queue.expirationTime > update.expirationTime
  ) {
    queue.expirationTime = update.expirationTime;
  }
}

results matching ""

    No results matching ""