@@ -71,38 +71,28 @@ export function processUpdateQueue<State>(
71
71
instance : any ,
72
72
renderExpirationTime : ExpirationTime ,
73
73
): void {
74
- // This is always non-null on a ClassComponent or HostRoot
75
74
const queue: UpdateQueue <State > = (workInProgress .updateQueue : any);
76
75
77
76
hasForceUpdate = false ;
78
77
79
78
let firstBaseUpdate = queue .firstBaseUpdate ;
80
79
let lastBaseUpdate = queue .lastBaseUpdate ;
81
80
82
- // Check if there are pending updates. If so, transfer them to the base queue.
83
81
// 查看当前fiber上的BaseQueue是否有没处理的update,有的话把pendingQueue链到后面,没有就直接复制,清空pendingQueue
84
82
let pendingQueue = queue .shared .pending ;
85
83
if (pendingQueue !== null ) {
86
84
queue .shared .pending = null ;
87
85
88
- // The pending queue is circular. Disconnect the pointer between first
89
- // and last so that it's non-circular.
90
86
const lastPendingUpdate = pendingQueue;
91
87
const firstPendingUpdate = lastPendingUpdate .next ;
92
88
lastPendingUpdate .next = null ;
93
- // Append pending updates to base queue
94
89
if (lastBaseUpdate === null ) {
95
90
firstBaseUpdate = firstPendingUpdate;
96
91
} else {
97
92
lastBaseUpdate .next = firstPendingUpdate;
98
93
}
99
94
lastBaseUpdate = lastPendingUpdate;
100
95
101
- // If there's a current queue, and it's different from the base queue, then
102
- // we need to transfer the updates to that queue, too. Because the base
103
- // queue is a singly-linked list with no cycles, we can append to both
104
- // lists and take advantage of structural sharing.
105
- // TODO: Pass `current` as argument
106
96
const current = workInProgress .alternate ;
107
97
if (current !== null ) {
108
98
// This is always non-null on a ClassComponent or HostRoot
@@ -119,9 +109,7 @@ export function processUpdateQueue<State>(
119
109
}
120
110
}
121
111
122
- // These values may change as we process the queue.
123
112
if (firstBaseUpdate !== null ) {
124
- // Iterate through the list of updates to compute the result.
125
113
let newState = queue .baseState ;
126
114
let newExpirationTime = NoWork;
127
115
@@ -134,9 +122,6 @@ export function processUpdateQueue<State>(
134
122
const updateExpirationTime = update .expirationTime ;
135
123
if (updateExpirationTime < renderExpirationTime) {
136
124
// update优先级不够,不执行,拷贝一份当前的update,完事后赋值给BaseQueue,等待下一次调度
137
- // Priority is insufficient. Skip this update. If this is the first
138
- // skipped update, the previous update/state is the new base
139
- // update/state.
140
125
const clone: Update <State > = {
141
126
expirationTime: update .expirationTime ,
142
127
suspenseConfig: update .suspenseConfig ,
@@ -153,13 +138,11 @@ export function processUpdateQueue<State>(
153
138
} else {
154
139
newLastBaseUpdate = newLastBaseUpdate .next = clone;
155
140
}
156
- // Update the remaining priority in the queue.
157
141
if (updateExpirationTime > newExpirationTime) {
158
142
newExpirationTime = updateExpirationTime;
159
143
}
160
144
} else {
161
145
// update先级足够
162
- // This update does have sufficient priority.
163
146
164
147
// 应该是中断相关,猜测是需要保证update调用的连续性,否则可能有多个结果
165
148
if (newLastBaseUpdate !== null ) {
@@ -212,13 +195,6 @@ export function processUpdateQueue<State>(
212
195
queue .firstBaseUpdate = newFirstBaseUpdate;
213
196
queue .lastBaseUpdate = newLastBaseUpdate;
214
197
215
- // Set the remaining expiration time to be whatever is remaining in the queue.
216
- // This should be fine because the only two other things that contribute to
217
- // expiration time are props and context. We're already in the middle of the
218
- // begin phase by the time we start processing the queue, so we've already
219
- // dealt with the props. Context in components that specify
220
- // shouldComponentUpdate is tricky; but we'll have to account for
221
- // that regardless.
222
198
markUnprocessedUpdateTime (newExpirationTime);
223
199
workInProgress .expirationTime = newExpirationTime;
224
200
workInProgress .memoizedState = newState;
@@ -259,7 +235,6 @@ function mountState<S>(
259
235
): [S, Dispatch<BasicStateAction<S>>] {
260
236
const hook = mountWorkInProgressHook ();
261
237
if (typeof initialState === ' function' ) {
262
- // $FlowFixMe: Flow doesn't like mixed types
263
238
initialState = initialState ();
264
239
}
265
240
hook .memoizedState = hook .baseState = initialState;
@@ -294,17 +269,12 @@ function updateReducer<S, I, A>(
294
269
295
270
const current: Hook = ();
296
271
297
- // The last rebase update that is NOT part of the base state.
298
272
let baseQueue = current .baseQueue ;
299
273
300
- // The last pending update that hasn't been processed yet.
301
274
// 把pengdingQueue链接到baseQueue后,清除pengding
302
275
const pendingQueue = queue .pending ;
303
276
if (pendingQueue !== null ) {
304
- // We have new updates that haven't been processed yet.
305
- // We'll add them to the base queue.
306
277
if (baseQueue !== null ) {
307
- // Merge the pending queue and the base queue.
308
278
const baseFirst = baseQueue .next ;
309
279
const pendingFirst = pendingQueue .next ;
310
280
baseQueue .next = pendingFirst;
@@ -315,7 +285,6 @@ function updateReducer<S, I, A>(
315
285
}
316
286
317
287
if (baseQueue !== null ) {
318
- // We have a queue to process.
319
288
const first = baseQueue .next ;
320
289
let newState = current .baseState ;
321
290
@@ -327,9 +296,6 @@ function updateReducer<S, I, A>(
327
296
const updateExpirationTime = update .expirationTime ;
328
297
if (updateExpirationTime < renderExpirationTime) {
329
298
// 优先级不足,把这个update链到newBaseQueueFirst,等循环结束后,重设到baseQueue, 等待下一次的调度
330
- // Priority is insufficient. Skip this update. If this is the first
331
- // skipped update, the previous update/state is the new base
332
- // update/state.
333
299
const clone: Update <S , A > = {
334
300
expirationTime: update .expirationTime ,
335
301
suspenseConfig: update .suspenseConfig ,
@@ -344,17 +310,14 @@ function updateReducer<S, I, A>(
344
310
} else {
345
311
newBaseQueueLast = newBaseQueueLast .next = clone;
346
312
}
347
- // Update the remaining priority in the queue.
348
313
if (updateExpirationTime > currentlyRenderingFiber .expirationTime ) {
349
314
currentlyRenderingFiber .expirationTime = updateExpirationTime;
350
315
markUnprocessedUpdateTime (updateExpirationTime);
351
316
}
352
317
} else {
353
- // This update does have sufficient priority.
354
-
355
318
if (newBaseQueueLast !== null ) {
356
319
const clone: Update <S , A > = {
357
- expirationTime: Sync, // This update is going to be committed so we never want uncommit it.
320
+ expirationTime: Sync,
358
321
suspenseConfig: update .suspenseConfig ,
359
322
action: update .action ,
360
323
eagerReducer: update .eagerReducer ,
@@ -364,21 +327,8 @@ function updateReducer<S, I, A>(
364
327
newBaseQueueLast = newBaseQueueLast .next = clone;
365
328
}
366
329
367
- // Mark the event time of this update as relevant to this render pass.
368
- // TODO: This should ideally use the true event time of this update rather than
369
- // its priority which is a derived and not reverseable value.
370
- // TODO: We should skip this update if it was already committed but currently
371
- // we have no way of detecting the difference between a committed and suspended
372
- // update here.
373
- markRenderEventTimeAndConfig (
374
- updateExpirationTime,
375
- update .suspenseConfig ,
376
- );
377
-
378
330
// 根据reducer处理旧state,生成新state
379
331
if (update .eagerReducer === reducer) {
380
- // If this update was processed eagerly, and its reducer matches the
381
- // current reducer, we can use the eagerly computed state.
382
332
newState = ((update .eagerState : any): S );
383
333
} else {
384
334
const action = update .action ;
@@ -439,11 +389,9 @@ function dispatchAction<S, A>(
439
389
next: (null: any),
440
390
};
441
391
442
- // Append the update to the end of the list.
443
392
// 把新update挂载到pending上
444
393
const pending = queue .pending ;
445
394
if (pending === null ) {
446
- // This is the first update. Create a circular list.
447
395
update .next = update;
448
396
} else {
449
397
update .next = pending .next ;
@@ -457,38 +405,24 @@ function dispatchAction<S, A>(
457
405
(alternate !== null && alternate === currentlyRenderingFiber)
458
406
) {
459
407
// 在render阶段创建了更新,需要确认是不是死循环
460
- // This is a render phase update. Stash it in a lazily-created map of
461
- // queue -> linked list of updates. After this render pass, we'll restart
462
- // and apply the stashed updates on top of the work-in-progress hook.
463
408
didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true ;
464
409
update .expirationTime = renderExpirationTime;
465
410
} else {
466
411
if (
467
412
fiber .expirationTime === NoWork &&
468
413
(alternate === null || alternate .expirationTime === NoWork)
469
414
) {
470
- // The queue is currently empty, which means we can eagerly compute the
471
- // next state before entering the render phase. If the new state is the
472
- // same as the current state, we may be able to bail out entirely.
473
415
const lastRenderedReducer = queue .lastRenderedReducer ;
474
416
if (lastRenderedReducer !== null ) {
475
417
let prevDispatcher;
476
418
try {
477
419
const currentState: S = (queue .lastRenderedState : any);
478
420
// 根据[state, setState],根据setState创建出新的state
479
421
const eagerState = lastRenderedReducer (currentState, action);
480
- // Stash the eagerly computed state, and the reducer used to compute
481
- // it, on the update object. If the reducer hasn't changed by the
482
- // time we enter the render phase, then the eager state can be used
483
- // without calling the reducer again.
484
422
update .eagerReducer = lastRenderedReducer;
485
423
update .eagerState = eagerState;
486
424
// 新老state对比,没有更新则可以不启动调度
487
425
if (is (eagerState, currentState)) {
488
- // Fast path. We can bail out without scheduling React to re-render.
489
- // It's still possible that we'll need to rebase this update later,
490
- // if the component re-renders for a different reason and by that
491
- // time the reducer has changed.
492
426
return ;
493
427
}
494
428
} catch (error) {
0 commit comments