diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js
index 338191f23666c..b88f17c1cb168 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js
@@ -1681,11 +1681,7 @@ function getRemainingWorkInPrimaryTree(
// This boundary already timed out. Check if this render includes the level
// that previously suspended.
const baseTime = currentSuspenseState.baseTime;
- if (
- baseTime !== NoWork &&
- baseTime < renderExpirationTime &&
- baseTime > currentChildExpirationTime
- ) {
+ if (baseTime !== NoWork && baseTime < renderExpirationTime) {
// There's pending work at a lower level that might now be unblocked.
return baseTime;
}
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js
index 4fde99d80c715..6fbfd5cd97077 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js
@@ -1681,11 +1681,7 @@ function getRemainingWorkInPrimaryTree(
// This boundary already timed out. Check if this render includes the level
// that previously suspended.
const baseTime = currentSuspenseState.baseTime;
- if (
- baseTime !== NoWork &&
- baseTime < renderExpirationTime &&
- baseTime > currentChildExpirationTime
- ) {
+ if (baseTime !== NoWork && baseTime < renderExpirationTime) {
// There's pending work at a lower level that might now be unblocked.
return baseTime;
}
diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
index cfe3d244b5103..5f5469bcd9045 100644
--- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
@@ -3869,4 +3869,53 @@ describe('ReactSuspenseWithNoopRenderer', () => {
expect(root).toMatchRenderedOutput();
});
});
+
+ it('regression: #18657', async () => {
+ const {useState} = React;
+
+ let setText;
+ function App() {
+ const [text, _setText] = useState('A');
+ setText = _setText;
+ return ;
+ }
+
+ const root = ReactNoop.createRoot();
+ await ReactNoop.act(async () => {
+ await resolveText('A');
+ root.render(
+ }>
+
+ ,
+ );
+ });
+ expect(Scheduler).toHaveYielded(['A']);
+ expect(root).toMatchRenderedOutput();
+
+ await ReactNoop.act(async () => {
+ setText('B');
+ Scheduler.unstable_runWithPriority(
+ Scheduler.unstable_IdlePriority,
+ () => {
+ setText('B');
+ },
+ );
+ // Suspend the first update. The second update doesn't run because it has
+ // Idle priority.
+ expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
+
+ // Commit the fallback. Now we'll try working on Idle.
+ jest.runAllTimers();
+
+ // It also suspends.
+ expect(Scheduler).toFlushAndYield(['Suspend! [B]']);
+ });
+
+ await ReactNoop.act(async () => {
+ setText('B');
+ await resolveText('B');
+ });
+ expect(Scheduler).toHaveYielded(['Promise resolved [B]', 'B']);
+ expect(root).toMatchRenderedOutput();
+ });
});