@@ -246,6 +246,12 @@ function warnOnFunctionType(returnFiber: Fiber) {
246
246
}
247
247
}
248
248
249
+ function resolveLazy ( lazyType ) {
250
+ const payload = lazyType . _payload ;
251
+ const init = lazyType . _init ;
252
+ return init ( payload ) ;
253
+ }
254
+
249
255
// This wrapper function exists because I expect to clone the code in each path
250
256
// to be able to optimize each path individually by branching early. This needs
251
257
// a compiler or we can do it manually. Helpers that don't need this branching
@@ -383,11 +389,32 @@ function ChildReconciler(shouldTrackSideEffects) {
383
389
element : ReactElement ,
384
390
lanes : Lanes ,
385
391
) : Fiber {
392
+ const elementType = element . type ;
393
+ if ( elementType === REACT_FRAGMENT_TYPE ) {
394
+ return updateFragment (
395
+ returnFiber ,
396
+ current ,
397
+ element . props . children ,
398
+ lanes ,
399
+ element . key ,
400
+ ) ;
401
+ }
386
402
if ( current !== null ) {
387
403
if (
388
- current . elementType === element . type ||
404
+ current . elementType === elementType ||
389
405
// Keep this check inline so it only runs on the false path:
390
- ( __DEV__ ? isCompatibleFamilyForHotReloading ( current , element ) : false )
406
+ ( __DEV__
407
+ ? isCompatibleFamilyForHotReloading ( current , element )
408
+ : false ) ||
409
+ // Lazy types should reconcile their resolved type.
410
+ // We need to do this after the Hot Reloading check above,
411
+ // because hot reloading has different semantics than prod because
412
+ // it doesn't resuspend. So we can't let the call below suspend.
413
+ ( enableLazyElements &&
414
+ typeof elementType === 'object' &&
415
+ elementType !== null &&
416
+ elementType . $$typeof === REACT_LAZY_TYPE &&
417
+ resolveLazy ( elementType ) === current . type )
391
418
) {
392
419
// Move based on index
393
420
const existing = useFiber ( current , element . props ) ;
@@ -551,15 +578,6 @@ function ChildReconciler(shouldTrackSideEffects) {
551
578
switch ( newChild . $$typeof ) {
552
579
case REACT_ELEMENT_TYPE : {
553
580
if ( newChild . key === key ) {
554
- if ( newChild . type === REACT_FRAGMENT_TYPE ) {
555
- return updateFragment (
556
- returnFiber ,
557
- oldFiber ,
558
- newChild . props . children ,
559
- lanes ,
560
- key ,
561
- ) ;
562
- }
563
581
return updateElement ( returnFiber , oldFiber , newChild , lanes ) ;
564
582
} else {
565
583
return null ;
@@ -622,15 +640,6 @@ function ChildReconciler(shouldTrackSideEffects) {
622
640
existingChildren . get (
623
641
newChild . key === null ? newIdx : newChild . key ,
624
642
) || null ;
625
- if ( newChild . type === REACT_FRAGMENT_TYPE ) {
626
- return updateFragment (
627
- returnFiber ,
628
- matchedFiber ,
629
- newChild . props . children ,
630
- lanes ,
631
- newChild . key ,
632
- ) ;
633
- }
634
643
return updateElement ( returnFiber , matchedFiber , newChild , lanes ) ;
635
644
}
636
645
case REACT_PORTAL_TYPE : {
@@ -1101,39 +1110,44 @@ function ChildReconciler(shouldTrackSideEffects) {
1101
1110
// TODO: If key === null and child.key === null, then this only applies to
1102
1111
// the first item in the list.
1103
1112
if ( child . key === key ) {
1104
- switch ( child . tag ) {
1105
- case Fragment : {
1106
- if ( element . type === REACT_FRAGMENT_TYPE ) {
1107
- deleteRemainingChildren ( returnFiber , child . sibling ) ;
1108
- const existing = useFiber ( child , element . props . children ) ;
1109
- existing . return = returnFiber ;
1110
- if ( __DEV__ ) {
1111
- existing . _debugSource = element . _source ;
1112
- existing . _debugOwner = element . _owner ;
1113
- }
1114
- return existing ;
1113
+ const elementType = element . type ;
1114
+ if ( elementType === REACT_FRAGMENT_TYPE ) {
1115
+ if ( child . tag === Fragment ) {
1116
+ deleteRemainingChildren ( returnFiber , child . sibling ) ;
1117
+ const existing = useFiber ( child , element . props . children ) ;
1118
+ existing . return = returnFiber ;
1119
+ if ( __DEV__ ) {
1120
+ existing . _debugSource = element . _source ;
1121
+ existing . _debugOwner = element . _owner ;
1115
1122
}
1116
- break ;
1123
+ return existing ;
1117
1124
}
1118
- default : {
1119
- if (
1120
- child . elementType === element . type ||
1121
- // Keep this check inline so it only runs on the false path:
1122
- ( __DEV__
1123
- ? isCompatibleFamilyForHotReloading ( child , element )
1124
- : false )
1125
- ) {
1126
- deleteRemainingChildren ( returnFiber , child . sibling ) ;
1127
- const existing = useFiber ( child , element . props ) ;
1128
- existing . ref = coerceRef ( returnFiber , child , element ) ;
1129
- existing . return = returnFiber ;
1130
- if ( __DEV__ ) {
1131
- existing . _debugSource = element . _source ;
1132
- existing . _debugOwner = element . _owner ;
1133
- }
1134
- return existing ;
1125
+ } else {
1126
+ if (
1127
+ child . elementType === elementType ||
1128
+ // Keep this check inline so it only runs on the false path:
1129
+ ( __DEV__
1130
+ ? isCompatibleFamilyForHotReloading ( child , element )
1131
+ : false ) ||
1132
+ // Lazy types should reconcile their resolved type.
1133
+ // We need to do this after the Hot Reloading check above,
1134
+ // because hot reloading has different semantics than prod because
1135
+ // it doesn't resuspend. So we can't let the call below suspend.
1136
+ ( enableLazyElements &&
1137
+ typeof elementType === 'object' &&
1138
+ elementType !== null &&
1139
+ elementType . $$typeof === REACT_LAZY_TYPE &&
1140
+ resolveLazy ( elementType ) === child . type )
1141
+ ) {
1142
+ deleteRemainingChildren ( returnFiber , child . sibling ) ;
1143
+ const existing = useFiber ( child , element . props ) ;
1144
+ existing . ref = coerceRef ( returnFiber , child , element ) ;
1145
+ existing . return = returnFiber ;
1146
+ if ( __DEV__ ) {
1147
+ existing . _debugSource = element . _source ;
1148
+ existing . _debugOwner = element . _owner ;
1135
1149
}
1136
- break ;
1150
+ return existing ;
1137
1151
}
1138
1152
}
1139
1153
// Didn't match.
0 commit comments