@@ -90,7 +90,7 @@ import {
90
90
prepareToReadContext ,
91
91
calculateChangedBits ,
92
92
} from './ReactFiberNewContext' ;
93
- import { prepareToUseHooks , finishHooks , resetHooks } from './ReactFiberHooks' ;
93
+ import { resetHooks , renderWithHooks } from './ReactFiberHooks' ;
94
94
import { stopProfilerTimerIfRunning } from './ReactProfilerTimer' ;
95
95
import {
96
96
getMaskedContext ,
@@ -237,19 +237,37 @@ function updateForwardRef(
237
237
// The rest is a fork of updateFunctionComponent
238
238
let nextChildren ;
239
239
prepareToReadContext ( workInProgress , renderExpirationTime ) ;
240
- prepareToUseHooks ( current , workInProgress , renderExpirationTime ) ;
241
240
if ( __DEV__ ) {
242
241
ReactCurrentOwner . current = workInProgress ;
243
242
setCurrentPhase ( 'render' ) ;
244
- nextChildren = render ( nextProps , ref ) ;
243
+ nextChildren = renderWithHooks (
244
+ current ,
245
+ workInProgress ,
246
+ render ,
247
+ nextProps ,
248
+ ref ,
249
+ renderExpirationTime ,
250
+ ) ;
245
251
setCurrentPhase ( null ) ;
246
252
} else {
247
- nextChildren = render ( nextProps , ref ) ;
253
+ nextChildren = renderWithHooks (
254
+ current ,
255
+ workInProgress ,
256
+ render ,
257
+ nextProps ,
258
+ ref ,
259
+ renderExpirationTime ,
260
+ ) ;
261
+ }
262
+
263
+ if ( ( workInProgress . effectTag & PerformedWork ) === NoEffect ) {
264
+ return bailoutOnAlreadyFinishedWork (
265
+ current ,
266
+ workInProgress ,
267
+ renderExpirationTime ,
268
+ ) ;
248
269
}
249
- nextChildren = finishHooks ( render , nextProps , nextChildren , ref ) ;
250
270
251
- // React DevTools reads this flag.
252
- workInProgress . effectTag |= PerformedWork ;
253
271
reconcileChildren (
254
272
current ,
255
273
workInProgress ,
@@ -350,8 +368,6 @@ function updateMemoComponent(
350
368
) ;
351
369
}
352
370
}
353
- // React DevTools reads this flag.
354
- workInProgress . effectTag |= PerformedWork ;
355
371
let newChild = createWorkInProgress (
356
372
currentChild ,
357
373
nextProps ,
@@ -506,19 +522,37 @@ function updateFunctionComponent(
506
522
507
523
let nextChildren ;
508
524
prepareToReadContext ( workInProgress , renderExpirationTime ) ;
509
- prepareToUseHooks ( current , workInProgress , renderExpirationTime ) ;
510
525
if ( __DEV__ ) {
511
526
ReactCurrentOwner . current = workInProgress ;
512
527
setCurrentPhase ( 'render' ) ;
513
- nextChildren = Component ( nextProps , context ) ;
528
+ nextChildren = renderWithHooks (
529
+ current ,
530
+ workInProgress ,
531
+ Component ,
532
+ nextProps ,
533
+ context ,
534
+ renderExpirationTime ,
535
+ ) ;
514
536
setCurrentPhase ( null ) ;
515
537
} else {
516
- nextChildren = Component ( nextProps , context ) ;
538
+ nextChildren = renderWithHooks (
539
+ current ,
540
+ workInProgress ,
541
+ Component ,
542
+ nextProps ,
543
+ context ,
544
+ renderExpirationTime ,
545
+ ) ;
546
+ }
547
+
548
+ if ( ( workInProgress . effectTag & PerformedWork ) === NoEffect ) {
549
+ return bailoutOnAlreadyFinishedWork (
550
+ current ,
551
+ workInProgress ,
552
+ renderExpirationTime ,
553
+ ) ;
517
554
}
518
- nextChildren = finishHooks ( Component , nextProps , nextChildren , context ) ;
519
555
520
- // React DevTools reads this flag.
521
- workInProgress . effectTag |= PerformedWork ;
522
556
reconcileChildren (
523
557
current ,
524
558
workInProgress ,
@@ -1063,7 +1097,6 @@ function mountIndeterminateComponent(
1063
1097
const context = getMaskedContext ( workInProgress , unmaskedContext ) ;
1064
1098
1065
1099
prepareToReadContext ( workInProgress , renderExpirationTime ) ;
1066
- prepareToUseHooks ( null , workInProgress , renderExpirationTime ) ;
1067
1100
1068
1101
let value ;
1069
1102
@@ -1091,12 +1124,24 @@ function mountIndeterminateComponent(
1091
1124
}
1092
1125
1093
1126
ReactCurrentOwner . current = workInProgress ;
1094
- value = Component ( props , context ) ;
1127
+ value = renderWithHooks (
1128
+ null ,
1129
+ workInProgress ,
1130
+ Component ,
1131
+ props ,
1132
+ context ,
1133
+ renderExpirationTime ,
1134
+ ) ;
1095
1135
} else {
1096
- value = Component ( props , context ) ;
1136
+ value = renderWithHooks (
1137
+ null ,
1138
+ workInProgress ,
1139
+ Component ,
1140
+ props ,
1141
+ context ,
1142
+ renderExpirationTime ,
1143
+ ) ;
1097
1144
}
1098
- // React DevTools reads this flag.
1099
- workInProgress . effectTag |= PerformedWork ;
1100
1145
1101
1146
if (
1102
1147
typeof value === 'object' &&
@@ -1147,7 +1192,6 @@ function mountIndeterminateComponent(
1147
1192
} else {
1148
1193
// Proceed under the assumption that this is a function component
1149
1194
workInProgress . tag = FunctionComponent ;
1150
- value = finishHooks ( Component , props , value , context ) ;
1151
1195
reconcileChildren ( null , workInProgress , value , renderExpirationTime ) ;
1152
1196
if ( __DEV__ ) {
1153
1197
validateFunctionComponentInDev ( workInProgress , Component ) ;
@@ -1647,9 +1691,11 @@ function bailoutOnAlreadyFinishedWork(
1647
1691
1648
1692
if ( current !== null ) {
1649
1693
// Reuse previous context list
1650
- workInProgress . firstContextDependency = current . firstContextDependency ;
1694
+ workInProgress . contextDependencies = current . contextDependencies ;
1651
1695
}
1652
1696
1697
+ workInProgress . effectTag &= ~ PerformedWork ;
1698
+
1653
1699
if ( enableProfilerTimer ) {
1654
1700
// Don't update "base" render times for bailouts.
1655
1701
stopProfilerTimerIfRunning ( workInProgress ) ;
@@ -1680,11 +1726,12 @@ function beginWork(
1680
1726
if ( current !== null ) {
1681
1727
const oldProps = current . memoizedProps ;
1682
1728
const newProps = workInProgress . pendingProps ;
1683
- if (
1684
- oldProps === newProps &&
1685
- ! hasLegacyContextChanged ( ) &&
1686
- updateExpirationTime < renderExpirationTime
1687
- ) {
1729
+
1730
+ if ( oldProps !== newProps || hasLegacyContextChanged ( ) ) {
1731
+ // If props or context changed, mark the fiber as having performed work.
1732
+ // This may be unset if the props are determined to be equal later (memo).
1733
+ workInProgress . effectTag |= PerformedWork ;
1734
+ } else if ( updateExpirationTime < renderExpirationTime ) {
1688
1735
// This fiber does not have any pending work. Bailout without entering
1689
1736
// the begin phase. There's still some bookkeeping we that needs to be done
1690
1737
// in this optimized path, mostly pushing stuff onto the stack.
@@ -1767,6 +1814,9 @@ function beginWork(
1767
1814
renderExpirationTime ,
1768
1815
) ;
1769
1816
}
1817
+ } else {
1818
+ // No bailouts on initial mount.
1819
+ workInProgress . effectTag |= PerformedWork ;
1770
1820
}
1771
1821
1772
1822
// Before entering the begin phase, clear the expiration time.
0 commit comments