diff --git a/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js index 021d1d18c690a..8a3668cd0d396 100644 --- a/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js @@ -1786,70 +1786,103 @@ describe('ReactDOMServerSelectiveHydration', () => { document.body.removeChild(container); }); - describe('it can force hydration in response to', () => { + it('can force hydration in response to sync update', () => { + function Child({text}) { + Scheduler.unstable_yieldValue(`Child ${text}`); + return (spanRef = ref)}>{text}; + } + function App({text}) { + Scheduler.unstable_yieldValue(`App ${text}`); + return ( +
+ + + +
+ ); + } + let spanRef; - let initialSpan; - let root; - let App; - beforeEach(() => { - function Child({text}) { - Scheduler.unstable_yieldValue(`Child ${text}`); - return (spanRef = ref)}>{text}; - } - App = function({text}) { - Scheduler.unstable_yieldValue(`App ${text}`); - return ( -
- - - -
- ); - }; + const finalHTML = ReactDOMServer.renderToString(); + expect(Scheduler).toHaveYielded(['App A', 'Child A']); + const container = document.createElement('div'); + document.body.appendChild(container); + container.innerHTML = finalHTML; + const initialSpan = container.getElementsByTagName('span')[0]; + const root = ReactDOMClient.hydrateRoot(container, ); + expect(Scheduler).toFlushUntilNextPaint(['App A']); - const finalHTML = ReactDOMServer.renderToString(); - expect(Scheduler).toHaveYielded(['App A', 'Child A']); - const container = document.createElement('div'); - document.body.appendChild(container); - container.innerHTML = finalHTML; - initialSpan = container.getElementsByTagName('span')[0]; - root = ReactDOMClient.hydrateRoot(container, ); - expect(Scheduler).toFlushUntilNextPaint(['App A']); + ReactDOM.flushSync(() => { + root.render(); }); + expect(Scheduler).toHaveYielded(['App B', 'Child A', 'App B', 'Child B']); + expect(initialSpan).toBe(spanRef); + }); - it('sync update', () => { - ReactDOM.flushSync(() => { - root.render(); - }); - expect(Scheduler).toHaveYielded(['App B', 'Child A', 'App B', 'Child B']); - expect(initialSpan).toBe(spanRef); - }); + // @gate experimental || www + it('can force hydration in response to continuous update', () => { + function Child({text}) { + Scheduler.unstable_yieldValue(`Child ${text}`); + return (spanRef = ref)}>{text}; + } + function App({text}) { + Scheduler.unstable_yieldValue(`App ${text}`); + return ( +
+ + + +
+ ); + } - // @gate experimental || www - it('continuous update', () => { - TODO_scheduleContinuousSchedulerTask(() => { - root.render(); - }); - expect(Scheduler).toFlushAndYield([ - 'App B', - 'Child A', - 'App B', - 'Child B', - ]); - expect(initialSpan).toBe(spanRef); + let spanRef; + const finalHTML = ReactDOMServer.renderToString(); + expect(Scheduler).toHaveYielded(['App A', 'Child A']); + const container = document.createElement('div'); + document.body.appendChild(container); + container.innerHTML = finalHTML; + const initialSpan = container.getElementsByTagName('span')[0]; + const root = ReactDOMClient.hydrateRoot(container, ); + expect(Scheduler).toFlushUntilNextPaint(['App A']); + + TODO_scheduleContinuousSchedulerTask(() => { + root.render(); }); + expect(Scheduler).toFlushAndYield(['App B', 'Child A', 'App B', 'Child B']); + expect(initialSpan).toBe(spanRef); + }); - it('default update', () => { - ReactDOM.unstable_batchedUpdates(() => { - root.render(); - }); - expect(Scheduler).toFlushAndYield([ - 'App B', - 'Child A', - 'App B', - 'Child B', - ]); - expect(initialSpan).toBe(spanRef); + it('can force hydration in response to default update', () => { + function Child({text}) { + Scheduler.unstable_yieldValue(`Child ${text}`); + return (spanRef = ref)}>{text}; + } + function App({text}) { + Scheduler.unstable_yieldValue(`App ${text}`); + return ( +
+ + + +
+ ); + } + + let spanRef; + const finalHTML = ReactDOMServer.renderToString(); + expect(Scheduler).toHaveYielded(['App A', 'Child A']); + const container = document.createElement('div'); + document.body.appendChild(container); + container.innerHTML = finalHTML; + const initialSpan = container.getElementsByTagName('span')[0]; + const root = ReactDOMClient.hydrateRoot(container, ); + expect(Scheduler).toFlushUntilNextPaint(['App A']); + + ReactDOM.unstable_batchedUpdates(() => { + root.render(); }); + expect(Scheduler).toFlushAndYield(['App B', 'Child A', 'App B', 'Child B']); + expect(initialSpan).toBe(spanRef); }); }); diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js index b76de1f6dcd07..96113150be20f 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js @@ -138,7 +138,6 @@ import { import { NoLanes, NoLane, - SyncHydrationLane, SyncLane, NoTimestamp, claimNextTransitionLane, @@ -918,8 +917,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // TODO: Temporary until we confirm this warning is not fired. if ( existingCallbackNode == null && - existingCallbackPriority !== SyncLane && - existingCallbackPriority !== SyncHydrationLane + !includesSyncLane(existingCallbackPriority) ) { console.error( 'Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.', @@ -937,10 +935,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // Schedule a new callback. let newCallbackNode; - if ( - newCallbackPriority === SyncLane || - newCallbackPriority === SyncHydrationLane - ) { + if (includesSyncLane(newCallbackPriority)) { // Special case: Sync React callbacks are scheduled on a special // internal queue if (root.tag === LegacyRoot) { diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js index f7a8d79a54324..648daec30cfcd 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js @@ -138,7 +138,6 @@ import { import { NoLanes, NoLane, - SyncHydrationLane, SyncLane, NoTimestamp, claimNextTransitionLane, @@ -918,8 +917,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // TODO: Temporary until we confirm this warning is not fired. if ( existingCallbackNode == null && - existingCallbackPriority !== SyncLane && - existingCallbackPriority !== SyncHydrationLane + !includesSyncLane(existingCallbackPriority) ) { console.error( 'Expected scheduled callback to exist. This error is likely caused by a bug in React. Please file an issue.', @@ -937,10 +935,7 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) { // Schedule a new callback. let newCallbackNode; - if ( - newCallbackPriority === SyncLane || - newCallbackPriority === SyncHydrationLane - ) { + if (includesSyncLane(newCallbackPriority)) { // Special case: Sync React callbacks are scheduled on a special // internal queue if (root.tag === LegacyRoot) {