@@ -90,7 +90,7 @@ import {
90
90
prepareToReadContext ,
91
91
calculateChangedBits ,
92
92
} from './ReactFiberNewContext' ;
93
- import { resetHooks , renderWithHooks } from './ReactFiberHooks' ;
93
+ import { resetHooks , renderWithHooks , bailoutHooks } from './ReactFiberHooks' ;
94
94
import { stopProfilerTimerIfRunning } from './ReactProfilerTimer' ;
95
95
import {
96
96
getMaskedContext ,
@@ -128,6 +128,8 @@ import {
128
128
129
129
const ReactCurrentOwner = ReactSharedInternals . ReactCurrentOwner ;
130
130
131
+ let didReceiveUpdate : boolean = false ;
132
+
131
133
let didWarnAboutBadClass ;
132
134
let didWarnAboutContextTypeOnFunctionComponent ;
133
135
let didWarnAboutGetDerivedStateOnFunctionComponent ;
@@ -260,14 +262,17 @@ function updateForwardRef(
260
262
) ;
261
263
}
262
264
263
- if ( ( workInProgress . effectTag & PerformedWork ) === NoEffect ) {
265
+ if ( current !== null && ! didReceiveUpdate ) {
266
+ bailoutHooks ( current , workInProgress , renderExpirationTime ) ;
264
267
return bailoutOnAlreadyFinishedWork (
265
268
current ,
266
269
workInProgress ,
267
270
renderExpirationTime ,
268
271
) ;
269
272
}
270
273
274
+ // React DevTools reads this flag.
275
+ workInProgress . effectTag |= PerformedWork ;
271
276
reconcileChildren (
272
277
current ,
273
278
workInProgress ,
@@ -368,6 +373,8 @@ function updateMemoComponent(
368
373
) ;
369
374
}
370
375
}
376
+ // React DevTools reads this flag.
377
+ workInProgress . effectTag |= PerformedWork ;
371
378
let newChild = createWorkInProgress (
372
379
currentChild ,
373
380
nextProps ,
@@ -411,17 +418,20 @@ function updateSimpleMemoComponent(
411
418
// Inner propTypes will be validated in the function component path.
412
419
}
413
420
}
414
- if ( current !== null && updateExpirationTime < renderExpirationTime ) {
421
+ if ( current !== null ) {
415
422
const prevProps = current . memoizedProps ;
416
423
if (
417
424
shallowEqual ( prevProps , nextProps ) &&
418
425
current . ref === workInProgress . ref
419
426
) {
420
- return bailoutOnAlreadyFinishedWork (
421
- current ,
422
- workInProgress ,
423
- renderExpirationTime ,
424
- ) ;
427
+ didReceiveUpdate = false ;
428
+ if ( updateExpirationTime < renderExpirationTime ) {
429
+ return bailoutOnAlreadyFinishedWork (
430
+ current ,
431
+ workInProgress ,
432
+ renderExpirationTime ,
433
+ ) ;
434
+ }
425
435
}
426
436
}
427
437
return updateFunctionComponent (
@@ -545,14 +555,16 @@ function updateFunctionComponent(
545
555
) ;
546
556
}
547
557
548
- if ( ( workInProgress . effectTag & PerformedWork ) === NoEffect ) {
558
+ if ( current !== null && ! didReceiveUpdate ) {
559
+ bailoutHooks ( current , workInProgress , renderExpirationTime ) ;
549
560
return bailoutOnAlreadyFinishedWork (
550
561
current ,
551
562
workInProgress ,
552
563
renderExpirationTime ,
553
564
) ;
554
565
}
555
566
567
+ workInProgress . effectTag |= PerformedWork ;
556
568
reconcileChildren (
557
569
current ,
558
570
workInProgress ,
@@ -1142,6 +1154,8 @@ function mountIndeterminateComponent(
1142
1154
renderExpirationTime ,
1143
1155
) ;
1144
1156
}
1157
+ // React DevTools reads this flag.
1158
+ workInProgress . effectTag |= PerformedWork ;
1145
1159
1146
1160
if (
1147
1161
typeof value === 'object' &&
@@ -1682,6 +1696,10 @@ function updateContextConsumer(
1682
1696
return workInProgress . child ;
1683
1697
}
1684
1698
1699
+ export function markWorkInProgressReceivedUpdate ( ) {
1700
+ didReceiveUpdate = true ;
1701
+ }
1702
+
1685
1703
function bailoutOnAlreadyFinishedWork (
1686
1704
current : Fiber | null ,
1687
1705
workInProgress : Fiber ,
@@ -1694,8 +1712,6 @@ function bailoutOnAlreadyFinishedWork(
1694
1712
workInProgress . contextDependencies = current . contextDependencies ;
1695
1713
}
1696
1714
1697
- workInProgress . effectTag &= ~ PerformedWork ;
1698
-
1699
1715
if ( enableProfilerTimer ) {
1700
1716
// Don't update "base" render times for bailouts.
1701
1717
stopProfilerTimerIfRunning ( workInProgress ) ;
@@ -1730,8 +1746,9 @@ function beginWork(
1730
1746
if ( oldProps !== newProps || hasLegacyContextChanged ( ) ) {
1731
1747
// If props or context changed, mark the fiber as having performed work.
1732
1748
// This may be unset if the props are determined to be equal later (memo).
1733
- workInProgress . effectTag |= PerformedWork ;
1749
+ didReceiveUpdate = true ;
1734
1750
} else if ( updateExpirationTime < renderExpirationTime ) {
1751
+ didReceiveUpdate = false ;
1735
1752
// This fiber does not have any pending work. Bailout without entering
1736
1753
// the begin phase. There's still some bookkeeping we that needs to be done
1737
1754
// in this optimized path, mostly pushing stuff onto the stack.
@@ -1815,8 +1832,7 @@ function beginWork(
1815
1832
) ;
1816
1833
}
1817
1834
} else {
1818
- // No bailouts on initial mount.
1819
- workInProgress . effectTag |= PerformedWork ;
1835
+ didReceiveUpdate = false ;
1820
1836
}
1821
1837
1822
1838
// Before entering the begin phase, clear the expiration time.
0 commit comments