@@ -90,7 +90,7 @@ import {
9090 prepareToReadContext ,
9191 calculateChangedBits ,
9292} from './ReactFiberNewContext' ;
93- import { resetHooks , renderWithHooks } from './ReactFiberHooks' ;
93+ import { resetHooks , renderWithHooks , bailoutHooks } from './ReactFiberHooks' ;
9494import { stopProfilerTimerIfRunning } from './ReactProfilerTimer' ;
9595import {
9696 getMaskedContext ,
@@ -128,6 +128,8 @@ import {
128128
129129const ReactCurrentOwner = ReactSharedInternals . ReactCurrentOwner ;
130130
131+ let didReceiveUpdate : boolean = false ;
132+
131133let didWarnAboutBadClass ;
132134let didWarnAboutContextTypeOnFunctionComponent ;
133135let didWarnAboutGetDerivedStateOnFunctionComponent ;
@@ -260,14 +262,17 @@ function updateForwardRef(
260262 ) ;
261263 }
262264
263- if ( ( workInProgress . effectTag & PerformedWork ) === NoEffect ) {
265+ if ( current !== null && ! didReceiveUpdate ) {
266+ bailoutHooks ( current , workInProgress , renderExpirationTime ) ;
264267 return bailoutOnAlreadyFinishedWork (
265268 current ,
266269 workInProgress ,
267270 renderExpirationTime ,
268271 ) ;
269272 }
270273
274+ // React DevTools reads this flag.
275+ workInProgress . effectTag |= PerformedWork ;
271276 reconcileChildren (
272277 current ,
273278 workInProgress ,
@@ -368,6 +373,8 @@ function updateMemoComponent(
368373 ) ;
369374 }
370375 }
376+ // React DevTools reads this flag.
377+ workInProgress . effectTag |= PerformedWork ;
371378 let newChild = createWorkInProgress (
372379 currentChild ,
373380 nextProps ,
@@ -411,17 +418,20 @@ function updateSimpleMemoComponent(
411418 // Inner propTypes will be validated in the function component path.
412419 }
413420 }
414- if ( current !== null && updateExpirationTime < renderExpirationTime ) {
421+ if ( current !== null ) {
415422 const prevProps = current . memoizedProps ;
416423 if (
417424 shallowEqual ( prevProps , nextProps ) &&
418425 current . ref === workInProgress . ref
419426 ) {
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+ }
425435 }
426436 }
427437 return updateFunctionComponent (
@@ -545,14 +555,16 @@ function updateFunctionComponent(
545555 ) ;
546556 }
547557
548- if ( ( workInProgress . effectTag & PerformedWork ) === NoEffect ) {
558+ if ( current !== null && ! didReceiveUpdate ) {
559+ bailoutHooks ( current , workInProgress , renderExpirationTime ) ;
549560 return bailoutOnAlreadyFinishedWork (
550561 current ,
551562 workInProgress ,
552563 renderExpirationTime ,
553564 ) ;
554565 }
555566
567+ workInProgress . effectTag |= PerformedWork ;
556568 reconcileChildren (
557569 current ,
558570 workInProgress ,
@@ -1142,6 +1154,8 @@ function mountIndeterminateComponent(
11421154 renderExpirationTime ,
11431155 ) ;
11441156 }
1157+ // React DevTools reads this flag.
1158+ workInProgress . effectTag |= PerformedWork ;
11451159
11461160 if (
11471161 typeof value === 'object' &&
@@ -1682,6 +1696,10 @@ function updateContextConsumer(
16821696 return workInProgress . child ;
16831697}
16841698
1699+ export function markWorkInProgressReceivedUpdate ( ) {
1700+ didReceiveUpdate = true ;
1701+ }
1702+
16851703function bailoutOnAlreadyFinishedWork (
16861704 current : Fiber | null ,
16871705 workInProgress : Fiber ,
@@ -1694,8 +1712,6 @@ function bailoutOnAlreadyFinishedWork(
16941712 workInProgress . contextDependencies = current . contextDependencies ;
16951713 }
16961714
1697- workInProgress . effectTag &= ~ PerformedWork ;
1698-
16991715 if ( enableProfilerTimer ) {
17001716 // Don't update "base" render times for bailouts.
17011717 stopProfilerTimerIfRunning ( workInProgress ) ;
@@ -1730,8 +1746,9 @@ function beginWork(
17301746 if ( oldProps !== newProps || hasLegacyContextChanged ( ) ) {
17311747 // If props or context changed, mark the fiber as having performed work.
17321748 // This may be unset if the props are determined to be equal later (memo).
1733- workInProgress . effectTag |= PerformedWork ;
1749+ didReceiveUpdate = true ;
17341750 } else if ( updateExpirationTime < renderExpirationTime ) {
1751+ didReceiveUpdate = false ;
17351752 // This fiber does not have any pending work. Bailout without entering
17361753 // the begin phase. There's still some bookkeeping we that needs to be done
17371754 // in this optimized path, mostly pushing stuff onto the stack.
@@ -1815,8 +1832,7 @@ function beginWork(
18151832 ) ;
18161833 }
18171834 } else {
1818- // No bailouts on initial mount.
1819- workInProgress . effectTag |= PerformedWork ;
1835+ didReceiveUpdate = false ;
18201836 }
18211837
18221838 // Before entering the begin phase, clear the expiration time.
0 commit comments