Skip to content

Commit 81aaee5

Browse files
acdliteBrian Vaughn
and
Brian Vaughn
authored
Don't call onCommit et al if there are no effects (#19863)
* Don't call onCommit et al if there are no effects Checks `subtreeFlags` before scheduling an effect on the Profiler. * Fix failing Profiler tests The change to conditionally call Profiler commit hooks only if updates were scheduled broke a few of the Profiler tests. I've fixed the tests by either: * Adding a no-op passive effect into the subtree or * Converting onPostCommit to onCommit When possible, I opted to add the no-op passive effect to the tests since that that hook is called later (during passive phase) so the test is a little broader. In a few cases, this required adding awkward act() wrappers so I opted to go with onCommit instead. Co-authored-by: Brian Vaughn <bvaughn@fb.com>
1 parent 7355bf5 commit 81aaee5

File tree

4 files changed

+795
-714
lines changed

4 files changed

+795
-714
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.new.js

-15
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ import {
6060
Hydrating,
6161
ContentReset,
6262
DidCapture,
63-
Update,
64-
Passive,
6563
Ref,
6664
Deletion,
6765
ForceUpdateForLegacySuspense,
@@ -675,9 +673,6 @@ function updateProfiler(
675673
renderLanes: Lanes,
676674
){
677675
if(enableProfilerTimer){
678-
// TODO: Only call onRender et al if subtree has effects
679-
workInProgress.flags|=Update|Passive;
680-
681676
// Reset effect durations for the next eventual effect phase.
682677
// These are reset during render to allow the DevTools commit hook a chance to read them,
683678
conststateNode=workInProgress.stateNode;
@@ -3117,16 +3112,6 @@ function beginWork(
31173112
}
31183113
caseProfiler:
31193114
if(enableProfilerTimer){
3120-
// Profiler should only call onRender when one of its descendants actually rendered.
3121-
// TODO: Only call onRender et al if subtree has effects
3122-
consthasChildWork=includesSomeLane(
3123-
renderLanes,
3124-
workInProgress.childLanes,
3125-
);
3126-
if(hasChildWork){
3127-
workInProgress.flags|=Passive|Update;
3128-
}
3129-
31303115
// Reset effect durations for the next eventual effect phase.
31313116
// These are reset during render to allow the DevTools commit hook a chance to read them,
31323117
conststateNode=workInProgress.stateNode;

packages/react-reconciler/src/ReactFiberCommitWork.new.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ import {
6868
Placement,
6969
Snapshot,
7070
Update,
71+
Callback,
7172
PassiveMask,
7273
}from'./ReactFiberFlags';
7374
importgetComponentNamefrom'shared/getComponentName';
@@ -676,10 +677,17 @@ function commitLifeCycles(
676677
if(enableProfilerTimer){
677678
const{onCommit, onRender}=finishedWork.memoizedProps;
678679
const{effectDuration}=finishedWork.stateNode;
680+
constflags=finishedWork.flags;
679681

680682
constcommitTime=getCommitTime();
681683

682-
if(typeofonRender==='function'){
684+
constOnRenderFlag=Update;
685+
constOnCommitFlag=Callback;
686+
687+
if(
688+
(flags&OnRenderFlag)!==NoFlags&&
689+
typeofonRender==='function'
690+
){
683691
if(enableSchedulerTracing){
684692
onRender(
685693
finishedWork.memoizedProps.id,
@@ -703,7 +711,10 @@ function commitLifeCycles(
703711
}
704712

705713
if(enableProfilerCommitHooks){
706-
if(typeofonCommit==='function'){
714+
if(
715+
(flags&OnCommitFlag)!==NoFlags&&
716+
typeofonCommit==='function'
717+
){
707718
if(enableSchedulerTracing){
708719
onCommit(
709720
finishedWork.memoizedProps.id,

packages/react-reconciler/src/ReactFiberCompleteWork.new.js

+54-1
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,15 @@ import {
6767
import{
6868
Ref,
6969
Update,
70+
Callback,
71+
Passive,
72+
Deletion,
7073
NoFlags,
7174
DidCapture,
7275
Snapshot,
7376
MutationMask,
77+
LayoutMask,
78+
PassiveMask,
7479
StaticMask,
7580
}from'./ReactFiberFlags';
7681
importinvariantfrom'shared/invariant';
@@ -787,6 +792,8 @@ function bubbleProperties(completedWork: Fiber) {
787792
}
788793

789794
completedWork.childLanes=newChildLanes;
795+
796+
returndidBailout;
790797
}
791798

792799
functioncompleteWork(
@@ -804,7 +811,6 @@ function completeWork(
804811
caseForwardRef:
805812
caseFragment:
806813
caseMode:
807-
caseProfiler:
808814
caseContextConsumer:
809815
caseMemoComponent:
810816
bubbleProperties(workInProgress);
@@ -966,6 +972,53 @@ function completeWork(
966972
bubbleProperties(workInProgress);
967973
returnnull;
968974
}
975+
caseProfiler: {
976+
constdidBailout=bubbleProperties(workInProgress);
977+
if(!didBailout){
978+
// Use subtreeFlags to determine which commit callbacks should fire.
979+
// TODO: Move this logic to the commit phase, since we already check if
980+
// a fiber's subtree contains effects. Refactor the commit phase's
981+
// depth-first traversal so that we can put work tag-specific logic
982+
// before or after committing a subtree's effects.
983+
constOnRenderFlag=Update;
984+
constOnCommitFlag=Callback;
985+
constOnPostCommitFlag=Passive;
986+
constsubtreeFlags=workInProgress.subtreeFlags;
987+
constflags=workInProgress.flags;
988+
letnewFlags=flags;
989+
990+
// Call onRender any time this fiber or its subtree are worked on, even
991+
// if there are no effects
992+
newFlags|=OnRenderFlag;
993+
994+
// Call onCommit only if the subtree contains layout work, or if it
995+
// contains deletions, since those might result in unmount work, which
996+
// we include in the same measure.
997+
// TODO: Can optimize by using a static flag to track whether a tree
998+
// contains layout effects, like we do for passive effects.
999+
if(
1000+
(flags&(LayoutMask|Deletion))!==NoFlags||
1001+
(subtreeFlags&(LayoutMask|Deletion))!==NoFlags
1002+
){
1003+
newFlags|=OnCommitFlag;
1004+
}
1005+
1006+
// Call onPostCommit only if the subtree contains passive work.
1007+
// Don't have to check for deletions, because Deletion is already
1008+
// a passive flag.
1009+
if(
1010+
(flags&PassiveMask)!==NoFlags||
1011+
(subtreeFlags&PassiveMask)!==NoFlags
1012+
){
1013+
newFlags|=OnPostCommitFlag;
1014+
}
1015+
workInProgress.flags=newFlags;
1016+
}else{
1017+
// This fiber and its subtree bailed out, so don't fire any callbacks.
1018+
}
1019+
1020+
returnnull;
1021+
}
9691022
caseSuspenseComponent: {
9701023
popSuspenseContext(workInProgress);
9711024
constnextState: null|SuspenseState=workInProgress.memoizedState;

0 commit comments

Comments
 (0)
close