Skip to content

Commit 62406b0

Browse files
committed
Support hidden deprioritization in Batched Mode
Hidden trees will tear and commit in a separate render, as in Concurrent Mode. Unlike Concurrent Mode, once the hidden tree begins, it will finish without yielding.
1 parent 025b07b commit 62406b0

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,7 @@ import {
8484
Never,
8585
computeAsyncExpiration,
8686
} from './ReactFiberExpirationTime';
87-
import {
88-
ConcurrentMode,
89-
NoMode,
90-
ProfileMode,
91-
StrictMode,
92-
BatchedMode,
93-
} from './ReactTypeOfMode';
87+
import {NoMode, ProfileMode, StrictMode, BatchedMode} from './ReactTypeOfMode';
9488
import {
9589
shouldSetTextContent,
9690
shouldDeprioritizeSubtree,
@@ -980,7 +974,7 @@ function updateHostComponent(current, workInProgress, renderExpirationTime) {
980974

981975
// Check the host config to see if the children are offscreen/hidden.
982976
if (
983-
workInProgress.mode & ConcurrentMode &&
977+
workInProgress.mode & BatchedMode &&
984978
renderExpirationTime !== Never &&
985979
shouldDeprioritizeSubtree(type, nextProps)
986980
) {

packages/react-reconciler/src/ReactFiberScheduler.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import {
6464
BatchedMode,
6565
ConcurrentMode,
6666
} from './ReactTypeOfMode';
67+
import {ConcurrentRoot} from 'shared/ReactRootTags';
6768
import {
6869
HostRoot,
6970
ClassComponent,
@@ -776,6 +777,10 @@ function renderRoot(
776777
'Should not already be working.',
777778
);
778779

780+
if (root.tag !== ConcurrentRoot) {
781+
isSync = true;
782+
}
783+
779784
if (enableUserTimingAPI && expirationTime !== Sync) {
780785
const didExpire = isSync;
781786
stopRequestCallbackTimer(didExpire);

packages/react-reconciler/src/__tests__/ReactBatchedMode-test.internal.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,4 +161,46 @@ describe('ReactBatchedMode', () => {
161161
expect(Scheduler).toFlushExpired(['A1']);
162162
expect(root).toMatchRenderedOutput('A1B1');
163163
});
164+
165+
it('hidden subtrees are deprioritized but not yieldy', () => {
166+
const {useEffect} = React;
167+
168+
const root = ReactNoop.createSyncRoot();
169+
function App() {
170+
useEffect(() => Scheduler.yieldValue('Commit'));
171+
return (
172+
<Suspense fallback={<Text text="Loading..." />}>
173+
<div hidden={true}>
174+
<Text text="A" />
175+
<Text text="B" />
176+
<Text text="C" />
177+
</div>
178+
<div>
179+
<Text text="D" />
180+
<Text text="E" />
181+
<Text text="F" />
182+
</div>
183+
</Suspense>
184+
);
185+
}
186+
187+
root.render(<App />);
188+
expect(Scheduler).toFlushAndYieldThrough(['D', 'E', 'F', 'Commit']);
189+
expect(root).toMatchRenderedOutput(
190+
<React.Fragment>
191+
<div hidden={true} />
192+
<div>DEF</div>
193+
</React.Fragment>,
194+
);
195+
196+
Scheduler.unstable_flushNumberOfYields(1);
197+
expect(Scheduler).toHaveYielded(['A', 'B', 'C']);
198+
Scheduler.flushAll();
199+
expect(root).toMatchRenderedOutput(
200+
<React.Fragment>
201+
<div hidden={true}>ABC</div>
202+
<div>DEF</div>
203+
</React.Fragment>,
204+
);
205+
});
164206
});

0 commit comments

Comments
 (0)