@@ -84,6 +84,7 @@ import {queueRecoverableErrors} from './ReactFiberWorkLoop.new';
84
84
let hydrationParentFiber : null | Fiber = null ;
85
85
let nextHydratableInstance : null | HydratableInstance = null ;
86
86
let isHydrating : boolean = false ;
87
+ let didSuspend : boolean = false ;
87
88
88
89
// Hydration errors that were thrown inside this boundary
89
90
let hydrationErrors : Array < mixed > | null = null ;
@@ -98,6 +99,12 @@ function warnIfHydrating() {
98
99
}
99
100
}
100
101
102
+ export function markDidSuspendWhileHydratingDEV ( ) {
103
+ if ( __DEV__ ) {
104
+ didSuspend = true ;
105
+ }
106
+ }
107
+
101
108
function enterHydrationState ( fiber : Fiber ) : boolean {
102
109
if ( ! supportsHydration ) {
103
110
return false ;
@@ -110,6 +117,7 @@ function enterHydrationState(fiber: Fiber): boolean {
110
117
hydrationParentFiber = fiber ;
111
118
isHydrating = true ;
112
119
hydrationErrors = null ;
120
+ didSuspend = false ;
113
121
return true ;
114
122
}
115
123
@@ -127,6 +135,7 @@ function reenterHydrationStateFromDehydratedSuspenseInstance(
127
135
hydrationParentFiber = fiber ;
128
136
isHydrating = true ;
129
137
hydrationErrors = null ;
138
+ didSuspend = false ;
130
139
if ( treeContext !== null ) {
131
140
restoreSuspendedTreeContext ( fiber , treeContext ) ;
132
141
}
@@ -185,6 +194,13 @@ function deleteHydratableInstance(
185
194
186
195
function warnNonhydratedInstance ( returnFiber : Fiber , fiber : Fiber ) {
187
196
if ( __DEV__ ) {
197
+ if ( didSuspend ) {
198
+ // Inside a boundary that already suspended. We're currently rendering the
199
+ // siblings of a suspended node. The mismatch may be due to the missing
200
+ // data, so it's probably a false positive.
201
+ return ;
202
+ }
203
+
188
204
switch ( returnFiber . tag ) {
189
205
case HostRoot : {
190
206
const parentContainer = returnFiber . stateNode . containerInfo ;
@@ -418,13 +434,15 @@ function prepareToHydrateHostInstance(
418
434
}
419
435
420
436
const instance : Instance = fiber . stateNode ;
437
+ const shouldWarnIfMismatchDev = ! didSuspend ;
421
438
const updatePayload = hydrateInstance (
422
439
instance ,
423
440
fiber . type ,
424
441
fiber . memoizedProps ,
425
442
rootContainerInstance ,
426
443
hostContext ,
427
444
fiber ,
445
+ shouldWarnIfMismatchDev ,
428
446
) ;
429
447
// TODO: Type this specific to this type of component.
430
448
fiber . updateQueue = ( updatePayload : any ) ;
@@ -446,7 +464,13 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
446
464
447
465
const textInstance : TextInstance = fiber . stateNode ;
448
466
const textContent : string = fiber . memoizedProps ;
449
- const shouldUpdate = hydrateTextInstance ( textInstance , textContent , fiber ) ;
467
+ const shouldWarnIfMismatchDev = ! didSuspend ;
468
+ const shouldUpdate = hydrateTextInstance (
469
+ textInstance ,
470
+ textContent ,
471
+ fiber ,
472
+ shouldWarnIfMismatchDev ,
473
+ ) ;
450
474
if ( shouldUpdate ) {
451
475
// We assume that prepareToHydrateHostTextInstance is called in a context where the
452
476
// hydration parent is the parent host component of this host text.
@@ -616,6 +640,7 @@ function resetHydrationState(): void {
616
640
hydrationParentFiber = null ;
617
641
nextHydratableInstance = null ;
618
642
isHydrating = false ;
643
+ didSuspend = false ;
619
644
}
620
645
621
646
export function upgradeHydrationErrorsToRecoverable ( ) : void {
0 commit comments