Skip to content

1. React18 - 更新队列(构建+处理)

构建过程

  • 更新数据结构

    jsx
    let fiber = {
      memoizedState: { id: 1 },
      updateQueue: {
        shared: {
          pending: null,
        },
      },
    };
    
    let update1 = {
      payload: {
        name: "123",
      },
    };
  • 构建过程

    "img"

  • 代码实现

    jsx
    function enqueueUpdate(fiber, update) {
      const updateQueue = fiber.updateQueue;
      const shared = updateQueue.shared;
      const pending = shared.pending;
      if (pending === null) {
        update.next = update;
      } else {
        //如果更新队列不为空的话,取出第一个更新
        update.next = pending.next;
        //然后让原来队列的最后一个的next指向新的next
        pending.next = update;
      }
      updateQueue.shared.pending = update;
    }

更新处理过程

  • 处理过程

    "img"

  • 代码实现

    jsx
    function processUpdateQueue(fiber) {
      const queue = fiber.updateQueue;
      const pending = queue.shared.pending;
      if (pending !== null) {
        queue.shared.pending = null;
        //最后一个更新
        const lastPendingUpdate = pending;
        const firstPendingUpdate = lastPendingUpdate.next;
        //把环状链接剪开
        lastPendingUpdate.next = null;
        let newState = fiber.memoizedState;
        let update = firstPendingUpdate;
        while (update) {
          newState = getStateFromUpdate(update, newState);
          update = update.next;
        }
        fiber.memoizedState = newState;
      }
    }
    
    function getStateFromUpdate(update, newState) {
      return Object.assign({}, newState, update.payload);
    }

完整demo

jsx
function initialUpdateQueue(fiber) {
  //创建一个新的更新队列
  //pending其实是一个循环链接
  const queue = {
    shared: {
      pending: null
    }
  }
  fiber.updateQueue = queue;
}
function createUpdate() {
  return {};
}
function enqueueUpdate(fiber, update) {
  const updateQueue = fiber.updateQueue;
  const shared = updateQueue.shared;
  const pending = shared.pending;
  if (pending === null) {
    update.next = update;
  } else {
    //如果更新队列不为空的话,取出第一个更新
    update.next = pending.next;
    //然后让原来队列的最后一个的next指向新的next
    pending.next = update;
  }
  updateQueue.shared.pending = update;
}
function processUpdateQueue(fiber) {
  const queue = fiber.updateQueue;
  const pending = queue.shared.pending;
  if (pending !== null) {
    queue.shared.pending = null;
    //最后一个更新
    const lastPendingUpdate = pending;
    const firstPendingUpdate = lastPendingUpdate.next;
    //把环状链接剪开
    lastPendingUpdate.next = null;
    let newState = fiber.memoizedState;
    let update = firstPendingUpdate;
    while (update) {
      newState = getStateFromUpdate(update, newState);
      update = update.next;
    }
    fiber.memoizedState = newState;
  }
}
function getStateFromUpdate(update, newState) {
  return Object.assign({}, newState, update.payload);
}

let fiber = { memoizedState: { id: 1 } };
initialUpdateQueue(fiber);

let update1 = createUpdate();
update1.payload = { name: '123' }
enqueueUpdate(fiber, update1)

let update2 = createUpdate();
update2.payload = { age: 14 }
enqueueUpdate(fiber, update2)

//基于老状态,计算新状态
processUpdateQueue(fiber);
console.log(fiber.memoizedState);

Released under the MIT License.