@samitouri / QOS-React-2 / commits / cfefc81ab2

Fix for #18657 (#18663)

* Failing test for #18657 * Remove incorrect priority check I think this was just poor factoring on my part in #18411. Honestly it doesn't make much sense to me, but my best guess is that I must have thought that when `baseTime > currentChildExpirationTime`, the function would fall through to the `currentChildExpirationTime < renderExpirationTime` branch below. Really I think just made an oopsie. Regardless, this logic is galaxy brainéd. A goal of the Lanes refactor I'm working on is to make these types of checks -- is there remaining work in this tree? -- a lot easier to think about. Hopefully.

Andrew Clark committed Apr 17, 2020 at 16:32 UTC cfefc81ab2f5103bedc9e45701e8c00c0689f499
3 files changed +51 -10
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+1 -5
@@ -1681,11 +1681,7 @@ function getRemainingWorkInPrimaryTree(
1681 // This boundary already timed out. Check if this render includes the level
1682 // that previously suspended.
1683 const baseTime = currentSuspenseState.baseTime;
1684 - if (
1685 - baseTime !== NoWork &&
1686 - baseTime < renderExpirationTime &&
1687 - baseTime > currentChildExpirationTime
1688 - ) {
1684 + if (baseTime !== NoWork && baseTime < renderExpirationTime) {
1685 // There's pending work at a lower level that might now be unblocked.
1686 return baseTime;
1687 }
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+1 -5
@@ -1681,11 +1681,7 @@ function getRemainingWorkInPrimaryTree(
1681 // This boundary already timed out. Check if this render includes the level
1682 // that previously suspended.
1683 const baseTime = currentSuspenseState.baseTime;
1684 - if (
1685 - baseTime !== NoWork &&
1686 - baseTime < renderExpirationTime &&
1687 - baseTime > currentChildExpirationTime
1688 - ) {
1684 + if (baseTime !== NoWork && baseTime < renderExpirationTime) {
1685 // There's pending work at a lower level that might now be unblocked.
1686 return baseTime;
1687 }
packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
+49
@@ -3869,4 +3869,53 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3869 expect(root).toMatchRenderedOutput(<span prop="b" />);
3870 });
3871 });
3872 +
3873 + it('regression: #18657', async () => {
3874 + const {useState} = React;
3875 +
3876 + let setText;
3877 + function App() {
3878 + const [text, _setText] = useState('A');
3879 + setText = _setText;
3880 + return <AsyncText text={text} />;
3881 + }
3882 +
3883 + const root = ReactNoop.createRoot();
3884 + await ReactNoop.act(async () => {
3885 + await resolveText('A');
3886 + root.render(
3887 + <Suspense fallback={<Text text="Loading..." />}>
3888 + <App />
3889 + </Suspense>,
3890 + );
3891 + });
3892 + expect(Scheduler).toHaveYielded(['A']);
3893 + expect(root).toMatchRenderedOutput(<span prop="A" />);
3894 +
3895 + await ReactNoop.act(async () => {
3896 + setText('B');
3897 + Scheduler.unstable_runWithPriority(
3898 + Scheduler.unstable_IdlePriority,
3899 + () => {
3900 + setText('B');
3901 + },
3902 + );
3903 + // Suspend the first update. The second update doesn't run because it has
3904 + // Idle priority.
3905 + expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
3906 +
3907 + // Commit the fallback. Now we'll try working on Idle.
3908 + jest.runAllTimers();
3909 +
3910 + // It also suspends.
3911 + expect(Scheduler).toFlushAndYield(['Suspend! [B]']);
3912 + });
3913 +
3914 + await ReactNoop.act(async () => {
3915 + setText('B');
3916 + await resolveText('B');
3917 + });
3918 + expect(Scheduler).toHaveYielded(['Promise resolved [B]', 'B']);
3919 + expect(root).toMatchRenderedOutput(<span prop="B" />);
3920 + });
3921 });