@@ -193,11 +193,8 @@ let workInProgressHook: Hook | null = null;
193
193
194
194
// Whether an update was scheduled during the currently executing render pass.
195
195
let didScheduleRenderPhaseUpdate : boolean = false ;
196
- // Lazily created map of render-phase updates
197
- let renderPhaseUpdates : Map <
198
- UpdateQueue < any , any > ,
199
- Update < any , any > ,
200
- > | null = null ;
196
+ // TODO: Move to custom dispatcher.
197
+ let isRerender = false ;
201
198
202
199
const RE_RENDER_LIMIT = 25 ;
203
200
@@ -396,7 +393,6 @@ export function renderWithHooks(
396
393
// workInProgressHook = null;
397
394
398
395
// didScheduleRenderPhaseUpdate = false;
399
- // renderPhaseUpdates = null;
400
396
401
397
// TODO Warn if no hooks are used at all during mount, then some are used during update.
402
398
// Currently we will identify the update render as a mount because memoizedState === null.
@@ -428,6 +424,8 @@ export function renderWithHooks(
428
424
let children = Component ( props , refOrContext ) ;
429
425
430
426
if ( didScheduleRenderPhaseUpdate ) {
427
+ isRerender = true ;
428
+
431
429
// Counter to prevent infinite loops.
432
430
let numberOfReRenders : number = 0 ;
433
431
do {
@@ -464,7 +462,7 @@ export function renderWithHooks(
464
462
children = Component ( props , refOrContext ) ;
465
463
} while ( didScheduleRenderPhaseUpdate ) ;
466
464
467
- renderPhaseUpdates = null ;
465
+ isRerender = false ;
468
466
}
469
467
470
468
// We can assume the previous dispatcher is always this one, since we set it
@@ -494,7 +492,6 @@ export function renderWithHooks(
494
492
495
493
// These were reset above
496
494
// didScheduleRenderPhaseUpdate = false;
497
- // renderPhaseUpdates = null;
498
495
499
496
invariant (
500
497
! didRenderTooFewHooks ,
@@ -540,7 +537,7 @@ export function resetHooks(): void {
540
537
}
541
538
542
539
didScheduleRenderPhaseUpdate = false ;
543
- renderPhaseUpdates = null ;
540
+ isRerender = false ;
544
541
}
545
542
546
543
function mountWorkInProgressHook ( ) : Hook {
@@ -676,15 +673,17 @@ function updateReducer<S, I, A>(
676
673
677
674
queue . lastRenderedReducer = reducer ;
678
675
679
- if ( renderPhaseUpdates !== null ) {
676
+ if ( isRerender ) {
680
677
// This is a re-render. Apply the new render phase updates to the previous
681
678
// work-in-progress hook.
682
679
const dispatch : Dispatch < A > = ( queue . dispatch : any ) ;
683
- // Render phase updates are stored in a map of queue -> linked list
684
- const firstRenderPhaseUpdate = renderPhaseUpdates . get ( queue ) ;
685
- if ( firstRenderPhaseUpdate !== undefined ) {
686
- renderPhaseUpdates . delete ( queue ) ;
687
- let newState = hook . memoizedState ;
680
+ const lastRenderPhaseUpdate = queue . pending ;
681
+ let newState = hook . memoizedState ;
682
+ if ( lastRenderPhaseUpdate !== null ) {
683
+ // The queue doesn't persist past this render pass.
684
+ queue .pending = null ;
685
+
686
+ const firstRenderPhaseUpdate = lastRenderPhaseUpdate . next ;
688
687
let update = firstRenderPhaseUpdate ;
689
688
do {
690
689
// Process this render phase update. We don't have to check the
@@ -693,7 +692,7 @@ function updateReducer<S, I, A>(
693
692
const action = update . action ;
694
693
newState = reducer ( newState , action ) ;
695
694
update = update . next ;
696
- } while ( update !== null ) ;
695
+ } while ( update !== firstRenderPhaseUpdate ) ;
697
696
698
697
// Mark that the fiber performed work, but only if the new state is
699
698
// different from the current state.
@@ -711,10 +710,8 @@ function updateReducer<S, I, A>(
711
710
}
712
711
713
712
queue . lastRenderedState = newState ;
714
-
715
- return [ newState , dispatch ] ;
716
713
}
717
- return [ hook . memoizedState , dispatch ] ;
714
+ return [ newState , dispatch ] ;
718
715
}
719
716
720
717
const current: Hook = (currentHook: any);
@@ -1239,80 +1236,56 @@ function dispatchAction<S, A>(
1239
1236
) ;
1240
1237
}
1241
1238
1242
- const alternate = fiber.alternate;
1239
+ const currentTime = requestCurrentTimeForUpdate();
1240
+ const suspenseConfig = requestCurrentSuspenseConfig();
1241
+ const expirationTime = computeExpirationForFiber(
1242
+ currentTime,
1243
+ fiber,
1244
+ suspenseConfig,
1245
+ );
1246
+
1247
+ const update: Update< S , A > = {
1248
+ expirationTime ,
1249
+ suspenseConfig ,
1250
+ action ,
1251
+ eagerReducer : null ,
1252
+ eagerState : null ,
1253
+ next : ( null : any ) ,
1254
+ } ;
1255
+
1256
+ if (__DEV__) {
1257
+ update . priority = getCurrentPriorityLevel ( ) ;
1258
+ }
1259
+
1260
+ // Append the update to the end of the list.
1261
+ const pending = queue.pending;
1262
+ if (pending === null) {
1263
+ // This is the first update. Create a circular list.
1264
+ update . next = update ;
1265
+ } else {
1266
+ const first = pending . next ;
1267
+ if ( first !== null ) {
1268
+ // Still circular.
1269
+ update. next = first ;
1270
+ }
1271
+ pending.next = update;
1272
+ }
1273
+ queue . pending = update ;
1274
+
1243
1275
if (
1244
- fiber === currentlyRenderingFiber ||
1245
- (alternate !== null && alternate === currentlyRenderingFiber )
1276
+ currentlyRenderingFiber !== null &&
1277
+ ( fiber === currentlyRenderingFiber ||
1278
+ fiber . alternate === currentlyRenderingFiber )
1246
1279
) {
1247
1280
// This is a render phase update. Stash it in a lazily-created map of
1248
1281
// queue -> linked list of updates. After this render pass, we'll restart
1249
1282
// and apply the stashed updates on top of the work-in-progress hook.
1250
1283
didScheduleRenderPhaseUpdate = true ;
1251
- const update : Update < S , A > = {
1252
- expirationTime : renderExpirationTime ,
1253
- suspenseConfig : null ,
1254
- action,
1255
- eagerReducer : null ,
1256
- eagerState : null ,
1257
- next : ( null : any ) ,
1258
- } ;
1259
- if ( __DEV__ ) {
1260
- update . priority = getCurrentPriorityLevel ( ) ;
1261
- }
1262
- if (renderPhaseUpdates === null) {
1263
- renderPhaseUpdates = new Map ( ) ;
1264
- }
1265
- const firstRenderPhaseUpdate = renderPhaseUpdates.get(queue);
1266
- if (firstRenderPhaseUpdate === undefined) {
1267
- renderPhaseUpdates . set ( queue , update ) ;
1268
- } else {
1269
- // Append the update to the end of the list.
1270
- let lastRenderPhaseUpdate = firstRenderPhaseUpdate ;
1271
- while ( lastRenderPhaseUpdate . next !== null ) {
1272
- lastRenderPhaseUpdate = lastRenderPhaseUpdate . next ;
1273
- }
1274
- lastRenderPhaseUpdate . next = update ;
1275
- }
1284
+ update . expirationTime = renderExpirationTime ;
1276
1285
} else {
1277
- const currentTime = requestCurrentTimeForUpdate ( ) ;
1278
- const suspenseConfig = requestCurrentSuspenseConfig ( ) ;
1279
- const expirationTime = computeExpirationForFiber (
1280
- currentTime ,
1281
- fiber ,
1282
- suspenseConfig ,
1283
- ) ;
1284
-
1285
- const update : Update < S , A > = {
1286
- expirationTime,
1287
- suspenseConfig,
1288
- action,
1289
- eagerReducer : null ,
1290
- eagerState : null ,
1291
- next : ( null : any ) ,
1292
- } ;
1293
-
1294
- if ( __DEV__ ) {
1295
- update . priority = getCurrentPriorityLevel ( ) ;
1296
- }
1297
-
1298
- // Append the update to the end of the list.
1299
- const pending = queue.pending;
1300
- if (pending === null) {
1301
- // This is the first update. Create a circular list.
1302
- update . next = update ;
1303
- } else {
1304
- const first = pending . next ;
1305
- if ( first !== null ) {
1306
- // Still circular.
1307
- update. next = first ;
1308
- }
1309
- pending.next = update;
1310
- }
1311
- queue . pending = update ;
1312
-
1313
1286
if (
1314
1287
fiber . expirationTime === NoWork &&
1315
- ( alternate === null || alternate . expirationTime === NoWork )
1288
+ ( fiber . alternate === null || fiber . alternate . expirationTime === NoWork )
1316
1289
) {
1317
1290
// The queue is currently empty, which means we can eagerly compute the
1318
1291
// next state before entering the render phase. If the new state is the
0 commit comments