Repository navigation
React@v19源码---Suspense原理 #10
MyPrototypeWhat
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
<Suspense>前言
看之前应该对
React的完整渲染流程有一个清晰的认知,否则很容易迷茫。Suspense
例子
现象就是现
loading...然后state<Suspense>updateSuspenseComponent
分为三大部分:
变量判断
渲染阶段
mountSuspenseFallbackChildren
mountSuspensePrimaryChildren
mountWorkInProgressOffscreenFiber / createFiberFromOffscreen
总结
上面代码可以看到:在首次渲染阶段,会优先展示
fallback,然后把子节点当做offscreen来生成fiber,然后挂载到父节点上。继续渲染流程。下一步
beginWork走到了OffscreenComponent这个判断中updateOffscreenComponent
没什么特别的,正常的渲染流程,执行到函数组件中的
use,use会将promise放在全局变量中,然后抛出一个异常,被catch住之后走到handleThrow中。handleThrow
getShellBoundary函数获取shellBoundary,shellBoundary代表最外层的sususpense组件.renderRootSync
当
handleThrow执行完之后,由于while(true)所以继续执行下面的判断逻辑throwAndUnwindWorkLoop
throwException
markSuspenseBoundaryShouldCapture
attachPingListener
unwindUnitOfWork
unwindWork
总结
suspense节点,赋值全局变量suspenseHandlerStackCursor.current,将子节点当成offscreen生成fiber,然后继续渲染。use,use会将promise保存在全局变量中,然后throw SuspenseExceptioncatch,执行handleThrow,通过各种条件判断设置workInProgressSuspendedReason值。renderRootSync中,通过判断workInProgressSuspendedReason执行throwAndUnwindWorkLoopthrowAndUnwindWorkLoop中做了两件事throwExceptionthrowException中找到最近的suspense给它打上ShouldCapture,updateQueue赋值为Set[promise],attachPingListener,缓存promise,并且监听promise状态更改,unwindUnitOfWorkfiber(函数组件)向上找到最近的 suspense,去掉ShouldCapture,打上DidCapture,将沿途的fiber都打上Incomplete,置空subtreeFlags,deletions,workInProgress设置为suspense,将workInProgressRootExitStatus设置为RootDidNotCompleteworkLoop,从suspense节点重新开始正常渲染阶段beginWork中再次回到updateSuspenseComponent,重新生成子节点fiber和fallback fiber,将fallback fiber返回出去作为下一次beginWork处理的节点render和commit阶段,渲染结束,此时fallback已经在页面上了,然后下一个eventLoop中promise.then触发,也就是pingSuspendedRootpingSuspendedRoot
更新阶段
All reactions