performWorkOnRoot方法解析
# 概览
performWorkOnRoot方法是React中核心渲染调度逻辑,处理根节点。
# 源码分析
# performWorkOnRoot方法
function performWorkOnRoot(root, lanes, forceSync) {
/* 前置校验:检查当前是否已经在执行渲染或者是处于提交状态,防止重复渲染
* executionContext:React的执行上下文标记
* RenderContext:渲染中
* CommitContext:提交中
*/
if ((executionContext & (RenderContext | CommitContext)) !== NoContext) {
throw new Error("Should not already be working.");
}
/**
* 决定渲染模式(并发 vs 同步)
*/
// 先判断是否满足并发渲染条件:非强制同步+非紧急更新+非过期更新,或当前是预渲染
// 满足则开启时间切片,shouldTimeSlice为true
const shouldTimeSlice =
(!forceSync &&
!includesBlockingLanes(root, lanes) &&
!includesExpiredLanes(root, lanes)) ||
checkIfRootIsPrerendering(root, lanes);
// 若启用时间切片,则用并发模式渲染renderRootConcurrent;否则用同步渲染renderRootSync
// exitStatus表示渲染结果
let exitStatus = shouldTimeSlice
? renderRootConcurrent(root, lanes)
: renderRootSync(root, lanes, true);
let renderWasConcurrent = shouldTimeSlice;
/**
* 循环处理渲染结果(异常重试/一致性校验)
* 逻辑解释:
* 1.如果渲染还在进行中(RootInProgress):标记根节点挂起,退出循环;
* 2.并发渲染一致性校验:如果并发渲染的 “草稿树” 和外部状态不一致,放弃并发,重新同步渲染;
* 3.普通错误处理:如果渲染报错,尝试获取重试优先级,重新渲染;
* 4.致命错误处理:如果是致命错误,重置渲染状态,标记根节点挂起;
* 5.无错误则完成并发渲染:把 “草稿树” 准备好,等待后续提交(Commit)。
*/
do {
if (exitStatus === RootInProgress) {
// 渲染还在进行中(在并发模式下可能暂停)
// 若是预渲染,且是同步渲染,则标记根节点挂起
if (workInProgressRootIsPrerendering && !shouldTimeSlice) {
markRootSuspended(root, lanes, NoLane, false);
}
// 跳出循环
break;
} else {
// 1.并发渲染一致性校验
let renderEndTime = 0;
// 获取正在渲染的 “草稿树”
const finishedWork = root.current.alternate;
if (
renderWasConcurrent &&
!isRenderConsistentWithExternalStores(finishedWork)
) {
// 若并发渲染结果和外部状态不一致,则重新调用同步渲染
exitStatus = renderRootSync(root, lanes, false);
renderWasConcurrent = false;
// 重试循环
continue;
}
// 渲染报错处理
if (exitStatus == RootErrored) {
const lanesThatJustErrored = lanes;
// 获取需要重试的优先级车道
const errorRetryLanes = getLanesToRetrySynchronouslyOnError(
root,
lanesThatJustErrored,
);
// 有可重试的车道,重新渲染
if (errorRetryLanes !== NoLanes) {
lanes = errorRetryLanes;
exitStatus = recoverFormConcurrentError(
root,
lanesThatJustErrored,
errorRetryLanes,
);
renderWasConcurrent = false;
// 重试成功,继续循环
if (exitStatus !== RootErrored) {
continue;
}
}
}
/*
* 致命错误处理
*/
if (exitStatus === RootFatalErrored) {
// 重置渲染栈,标记根节点为“挂起”
prepareFreshStack(root, NoLanes);
const didAttemptEntireTree = true;
markRootSuspended(root, lanes, NoLane, didAttemptEntireTree);
break;
}
// 调用finishConcurrentRender 完成并发渲染
finishConcurrentRender(
root,
exitStatus,
finishedWork,
lanes,
renderEndTime,
);
}
break;
} while (true);
// 确保后续调度
ensureRootIsScheduled(root);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
编辑 (opens new window)
上次更新: 2026/02/28, 10:12:14