5.state更新流程(setState里到底发生了什么)

2021-02-18  本文已影响0人  全栈潇晨

人人都能读懂的react源码解析(大厂高薪必备)

5.state更新流程(setState里到底发生了什么)

视频课程&调试demos

视频课程的目的是为了快速掌握react源码运行的过程和react中的scheduler、reconciler、renderer、fiber等,并且详细debug源码和分析,过程更清晰。

视频课程&调试demos

视频课程的目的是为了快速掌握react源码运行的过程和react中的scheduler、reconciler、renderer、fiber等,并且详细debug源码和分析,过程更清晰。

视频课程:进入课程

demos:demo

课程结构:

  1. 开篇(听说你还在艰难的啃react源码)
  2. react心智模型(来来来,让大脑有react思维吧)
  3. Fiber(我是在内存中的dom)
  4. 从legacy或concurrent开始(从入口开始,然后让我们奔向未来)
  5. state更新流程(setState里到底发生了什么)
  6. render阶段(厉害了,我有创建Fiber的技能)
  7. commit阶段(听说renderer帮我们打好标记了,映射真实节点吧)
  8. diff算法(妈妈再也不担心我的diff面试了)
  9. hooks源码(想知道Function Component是怎样保存状态的嘛)
  10. scheduler&lane模型(来看看任务是暂停、继续和插队的)
  11. concurrent mode(并发模式是什么样的)
  12. 手写迷你react(短小精悍就是我)

上一节我们介绍了react两种模式的入口函数到render阶段的调用过程,也就是mount首次渲染的流程,这节我们介绍在更新状态之后到render阶段的流程。

在react中触发状态更新的几种方式:

const shouldUpdate =
  checkHasForceUpdateAfterProcessing() ||
  checkShouldComponentUpdate(
    workInProgress,
    ctor,
    oldProps,
    newProps,
    oldState,
    newState,
    nextContext,
  );

3.enqueueForceUpdate之后会经历创建update,调度update等过程,接下来就来讲这些过程

enqueueSetState(inst, payload, callback) {
  const fiber = getInstance(inst);//fiber实例

  const eventTime = requestEventTime();
  const suspenseConfig = requestCurrentSuspenseConfig();
  
  const lane = requestUpdateLane(fiber, suspenseConfig);//优先级

  const update = createUpdate(eventTime, lane, suspenseConfig);//创建update

  update.payload = payload;

  if (callback !== undefined && callback !== null) {  //赋值回调
    update.callback = callback;
  }

  enqueueUpdate(fiber, update);//update加入updateQueue
  scheduleUpdateOnFiber(fiber, lane, eventTime);//调度update
}

状态更新整体流程

_18

创建Update

HostRoot或者ClassComponent触发更新后,会在函数createUpdate中创建update,并在后面的render阶段的beginWork中计算Update。FunctionComponent对应的Update在第11章讲,它和HostRoot或者ClassComponent的Update结构有些不一样
export function createUpdate(eventTime: number, lane: Lane): Update<*> {//创建update
  const update: Update<*> = {
    eventTime,
    lane,

    tag: UpdateState,
    payload: null,
    callback: null,

    next: null,
  };
  return update;
}

我们主要关注这些参数:

updateQueue:

对于HostRoot或者ClassComponent会在mount的时候使用initializeUpdateQueue创建updateQueue,然后将updateQueue挂载到fiber节点上
export function initializeUpdateQueue<State>(fiber: Fiber): void {
  const queue: UpdateQueue<State> = {
    baseState: fiber.memoizedState,
    firstBaseUpdate: null,
    lastBaseUpdate: null,
  shared: {
      pending: null,
    },
    effects: null,
  };
fiber.updateQueue = queue;
}

调度

在ensureRootIsScheduled中,scheduleCallback会以一个优先级调度render阶段的开始函数performSyncWorkOnRoot或者performConcurrentWorkOnRoot
if (newCallbackPriority === SyncLanePriority) {
  // 任务已经过期,需要同步执行render阶段
  newCallbackNode = scheduleSyncCallback(
    performSyncWorkOnRoot.bind(null, root)
  );
} else {
  // 根据任务优先级异步执行render阶段
  var schedulerPriorityLevel = lanePriorityToSchedulerPriority(
    newCallbackPriority
  );
  newCallbackNode = scheduleCallback(
    schedulerPriorityLevel,
    performConcurrentWorkOnRoot.bind(null, root)
  );
}

状态更新

classComponent状态计算发生在processUpdateQueue函数中,涉及很多链表操作,看图更加直白
_19

带优先级的状态更新

类似git提交,这里的c3意味着高优先级的任务,比如用户出发的事件,数据请求,同步执行的代码等。
_21
上一篇下一篇

猜你喜欢

热点阅读