diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js index 465ab8de1f190..f2bec4ec6a689 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js @@ -453,12 +453,6 @@ describe('ReactDOMServerPartialHydration', () => { Scheduler.unstable_flushAll(); jest.runAllTimers(); - expect(Scheduler).toHaveYielded([ - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client rendering. ' + - 'The usual way to fix this is to wrap the original update ' + - 'in startTransition.', - ]); expect(hydrated.length).toBe(1); expect(deleted.length).toBe(1); @@ -1102,12 +1096,6 @@ describe('ReactDOMServerPartialHydration', () => { root.render(); Scheduler.unstable_flushAll(); jest.runAllTimers(); - expect(Scheduler).toHaveYielded([ - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client ' + - 'rendering. The usual way to fix this is to wrap the original ' + - 'update in startTransition.', - ]); // Flushing now should delete the existing content and show the fallback. @@ -1191,12 +1179,6 @@ describe('ReactDOMServerPartialHydration', () => { // Flushing now should delete the existing content and show the fallback. Scheduler.unstable_flushAll(); jest.runAllTimers(); - expect(Scheduler).toHaveYielded([ - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client rendering. ' + - 'The usual way to fix this is to wrap the original update ' + - 'in startTransition.', - ]); expect(container.getElementsByTagName('span').length).toBe(1); expect(ref.current).toBe(span); @@ -1284,12 +1266,6 @@ describe('ReactDOMServerPartialHydration', () => { suspend = false; resolve(); await promise; - expect(Scheduler).toHaveYielded([ - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client rendering. ' + - 'The usual way to fix this is to wrap the original update ' + - 'in startTransition.', - ]); Scheduler.unstable_flushAll(); jest.runAllTimers(); @@ -1602,12 +1578,6 @@ describe('ReactDOMServerPartialHydration', () => { // Flushing now should delete the existing content and show the fallback. Scheduler.unstable_flushAll(); jest.runAllTimers(); - expect(Scheduler).toHaveYielded([ - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client rendering. ' + - 'The usual way to fix this is to wrap the original update ' + - 'in startTransition.', - ]); expect(container.getElementsByTagName('span').length).toBe(0); expect(ref.current).toBe(null); @@ -2360,12 +2330,6 @@ describe('ReactDOMServerPartialHydration', () => { // This will force all expiration times to flush. Scheduler.unstable_flushAll(); jest.runAllTimers(); - expect(Scheduler).toHaveYielded([ - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client rendering. ' + - 'The usual way to fix this is to wrap the original update ' + - 'in startTransition.', - ]); // This will now be a new span because we weren't able to hydrate before const newSpan = container.getElementsByTagName('span')[0]; diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js index dc0e80e7edbba..27c086160ffe0 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js @@ -2717,9 +2717,6 @@ function updateDehydratedSuspenseComponent( current, workInProgress, renderLanes, - // TODO: When we delete legacy mode, we should make this error argument - // required — every concurrent mode path that causes hydration to - // de-opt to client rendering should have an error message. null, ); } @@ -2809,25 +2806,20 @@ function updateDehydratedSuspenseComponent( } } - // If we have scheduled higher pri work above, this will probably just abort the render - // since we now have higher priority work, but in case it doesn't, we need to prepare to - // render something, if we time out. Even if that requires us to delete everything and - // skip hydration. - // Delay having to do this as long as the suspense timeout allows us. + // If we have scheduled higher pri work above, this will just abort the render + // since we now have higher priority work. We'll try to infinitely suspend until + // we yield. TODO: We could probably just force yielding earlier instead. renderDidSuspendDelayIfPossible(); - const capturedValue = createCapturedValue( - new Error( - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client rendering. ' + - 'The usual way to fix this is to wrap the original update ' + - 'in startTransition.', - ), - ); + // If we rendered synchronously, we won't yield so have to render something. + // This will cause us to delete any existing content. + // TODO: We should ideally have a sync hydration lane that we can apply to do + // a pass where we hydrate this subtree in place using the previous Context and then + // reapply the update afterwards. return retrySuspenseComponentWithoutHydrating( current, workInProgress, renderLanes, - capturedValue, + null, ); } else if (isSuspenseInstancePending(suspenseInstance)) { // This component is still pending more data from the server, so we can't hydrate its diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js index d26036c4553ed..c3fed9d3c46a1 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js @@ -2717,9 +2717,6 @@ function updateDehydratedSuspenseComponent( current, workInProgress, renderLanes, - // TODO: When we delete legacy mode, we should make this error argument - // required — every concurrent mode path that causes hydration to - // de-opt to client rendering should have an error message. null, ); } @@ -2809,25 +2806,20 @@ function updateDehydratedSuspenseComponent( } } - // If we have scheduled higher pri work above, this will probably just abort the render - // since we now have higher priority work, but in case it doesn't, we need to prepare to - // render something, if we time out. Even if that requires us to delete everything and - // skip hydration. - // Delay having to do this as long as the suspense timeout allows us. + // If we have scheduled higher pri work above, this will just abort the render + // since we now have higher priority work. We'll try to infinitely suspend until + // we yield. TODO: We could probably just force yielding earlier instead. renderDidSuspendDelayIfPossible(); - const capturedValue = createCapturedValue( - new Error( - 'This Suspense boundary received an update before it finished ' + - 'hydrating. This caused the boundary to switch to client rendering. ' + - 'The usual way to fix this is to wrap the original update ' + - 'in startTransition.', - ), - ); + // If we rendered synchronously, we won't yield so have to render something. + // This will cause us to delete any existing content. + // TODO: We should ideally have a sync hydration lane that we can apply to do + // a pass where we hydrate this subtree in place using the previous Context and then + // reapply the update afterwards. return retrySuspenseComponentWithoutHydrating( current, workInProgress, renderLanes, - capturedValue, + null, ); } else if (isSuspenseInstancePending(suspenseInstance)) { // This component is still pending more data from the server, so we can't hydrate its