Skip to content

Commit ee43263

Browse files
authored
Revert "Remove blocking mode and blocking root (#20888)" (#20916)
This reverts commit 553440b.
1 parent de0ee76 commit ee43263

36 files changed

+531
-81
lines changed

packages/react-dom/index.classic.fb.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export {
3030
unmountComponentAtNode,
3131
createRoot,
3232
createRoot as unstable_createRoot,
33+
createBlockingRoot,
34+
createBlockingRoot as unstable_createBlockingRoot,
3335
unstable_flushControlled,
3436
unstable_scheduleHydration,
3537
unstable_runWithPriority,

packages/react-dom/index.experimental.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export {
2020
unmountComponentAtNode,
2121
// exposeConcurrentModeAPIs
2222
createRoot as unstable_createRoot,
23+
createBlockingRoot as unstable_createBlockingRoot,
2324
unstable_flushControlled,
2425
unstable_scheduleHydration,
2526
// DO NOT USE: Temporarily exposing this to migrate off of Scheduler.runWithPriority.

packages/react-dom/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ export {
2121
unmountComponentAtNode,
2222
createRoot,
2323
createRoot as unstable_createRoot,
24+
createBlockingRoot,
25+
createBlockingRoot as unstable_createBlockingRoot,
2426
unstable_flushControlled,
2527
unstable_scheduleHydration,
2628
unstable_runWithPriority,

packages/react-dom/index.modern.fb.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export {
1515
version,
1616
createRoot,
1717
createRoot as unstable_createRoot,
18+
createBlockingRoot,
19+
createBlockingRoot as unstable_createBlockingRoot,
1820
unstable_flushControlled,
1921
unstable_scheduleHydration,
2022
unstable_runWithPriority,

packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,33 @@ describe('ReactDOMFiberAsync', () => {
593593
expect(containerC.textContent).toEqual('Finished');
594594
});
595595

596+
describe('createBlockingRoot', () => {
597+
// @gate experimental
598+
it('updates flush without yielding in the next event', () => {
599+
const root = ReactDOM.unstable_createBlockingRoot(container);
600+
601+
function Text(props) {
602+
Scheduler.unstable_yieldValue(props.text);
603+
return props.text;
604+
}
605+
606+
root.render(
607+
<>
608+
<Text text="A" />
609+
<Text text="B" />
610+
<Text text="C" />
611+
</>,
612+
);
613+
614+
// Nothing should have rendered yet
615+
expect(container.textContent).toEqual('');
616+
617+
// Everything should render immediately in the next event
618+
expect(Scheduler).toFlushExpired(['A', 'B', 'C']);
619+
expect(container.textContent).toEqual('ABC');
620+
});
621+
});
622+
596623
// @gate experimental
597624
it('unmounted roots should never clear newer root content from a container', () => {
598625
const ref = React.createRef();

packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ describe('ReactDOMServerPartialHydration', () => {
352352
}).toErrorDev(
353353
'Warning: Cannot hydrate Suspense in legacy mode. Switch from ' +
354354
'ReactDOM.hydrate(element, container) to ' +
355-
'ReactDOM.createRoot(container, { hydrate: true })' +
355+
'ReactDOM.createBlockingRoot(container, { hydrate: true })' +
356356
'.render(element) or remove the Suspense components from the server ' +
357357
'rendered components.' +
358358
'\n in Suspense (at **)' +

packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ describe('ReactDOMServerSuspense', () => {
127127
expect(divB.textContent).toBe('B');
128128

129129
act(() => {
130-
const root = ReactDOM.createRoot(parent, {hydrate: true});
130+
const root = ReactDOM.createBlockingRoot(parent, {hydrate: true});
131131
root.render(example);
132132
});
133133

packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,33 @@ describe('ReactTestUtils.act()', () => {
7272

7373
runActTests('legacy mode', renderLegacy, unmountLegacy, rerenderLegacy);
7474

75+
// and then in blocking mode
76+
if (__EXPERIMENTAL__) {
77+
let blockingRoot = null;
78+
const renderBatched = (el, dom) => {
79+
blockingRoot = ReactDOM.unstable_createBlockingRoot(dom);
80+
blockingRoot.render(el);
81+
};
82+
83+
const unmountBatched = dom => {
84+
if (blockingRoot !== null) {
85+
blockingRoot.unmount();
86+
blockingRoot = null;
87+
}
88+
};
89+
90+
const rerenderBatched = el => {
91+
blockingRoot.render(el);
92+
};
93+
94+
runActTests(
95+
'blocking mode',
96+
renderBatched,
97+
unmountBatched,
98+
rerenderBatched,
99+
);
100+
}
101+
75102
describe('unacted effects', () => {
76103
function App() {
77104
React.useEffect(() => {}, []);
@@ -97,6 +124,19 @@ describe('ReactTestUtils.act()', () => {
97124
]);
98125
});
99126

127+
// @gate experimental
128+
it('warns in blocking mode', () => {
129+
expect(() => {
130+
const root = ReactDOM.unstable_createBlockingRoot(
131+
document.createElement('div'),
132+
);
133+
root.render(<App />);
134+
Scheduler.unstable_flushAll();
135+
}).toErrorDev([
136+
'An update to App ran an effect, but was not wrapped in act(...)',
137+
]);
138+
});
139+
100140
// @gate experimental
101141
it('warns in concurrent mode', () => {
102142
expect(() => {
@@ -691,10 +731,14 @@ function runActTests(label, render, unmount, rerender) {
691731

692732
it('triggers fallbacks if available', async () => {
693733
if (label !== 'legacy mode') {
694-
// FIXME: Support for Concurrent Root intentionally removed
695-
// from the public version of `act`. It will be added back in
696-
// a future major version, Concurrent Root officially released.
697-
// Consider skipping all non-Legacy tests in this suite until then.
734+
// FIXME: Support for Blocking* and Concurrent Mode were
735+
// intentionally removed from the public version of `act`. It will
736+
// be added back in a future major version, before Blocking and and
737+
// Concurrent Mode are officially released. Consider disabling all
738+
// non-Legacy tests in this suite until then.
739+
//
740+
// *Blocking Mode actually does happen to work, though
741+
// not "officially" since it's an unreleased feature.
698742
return;
699743
}
700744

@@ -750,8 +794,10 @@ function runActTests(label, render, unmount, rerender) {
750794
// In Concurrent Mode, refresh transitions delay indefinitely.
751795
expect(document.querySelector('[data-test-id=spinner]')).toBeNull();
752796
} else {
753-
// In Legacy Mode, all fallbacks are forced to display,
754-
// even during a refresh transition.
797+
// In Legacy Mode and Blocking Mode, all fallbacks are forced to
798+
// display, even during a refresh transition.
799+
// TODO: Consider delaying indefinitely in Blocking Mode, to match
800+
// Concurrent Mode semantics.
755801
expect(
756802
document.querySelector('[data-test-id=spinner]'),
757803
).not.toBeNull();

packages/react-dom/src/__tests__/ReactUnmockedSchedulerWarning-test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,22 @@ it('should warn when rendering in concurrent mode', () => {
4343
ReactDOM.unstable_createRoot(document.createElement('div')).render(<App />);
4444
}).toErrorDev([]);
4545
});
46+
47+
// @gate experimental
48+
it('should warn when rendering in blocking mode', () => {
49+
expect(() => {
50+
ReactDOM.unstable_createBlockingRoot(document.createElement('div')).render(
51+
<App />,
52+
);
53+
}).toErrorDev(
54+
'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' +
55+
'to guarantee consistent behaviour across tests and browsers.',
56+
{withoutStack: true},
57+
);
58+
// does not warn twice
59+
expect(() => {
60+
ReactDOM.unstable_createBlockingRoot(document.createElement('div')).render(
61+
<App />,
62+
);
63+
}).toErrorDev([]);
64+
});

packages/react-dom/src/client/ReactDOM.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
unstable_renderSubtreeIntoContainer,
1919
unmountComponentAtNode,
2020
} from './ReactDOMLegacy';
21-
import {createRoot, isValidContainer} from './ReactDOMRoot';
21+
import {createRoot, createBlockingRoot, isValidContainer} from './ReactDOMRoot';
2222
import {createEventHandle} from './ReactDOMEventHandle';
2323

2424
import {
@@ -201,6 +201,7 @@ export {
201201
unmountComponentAtNode,
202202
// exposeConcurrentModeAPIs
203203
createRoot,
204+
createBlockingRoot,
204205
flushControlled as unstable_flushControlled,
205206
scheduleHydration as unstable_scheduleHydration,
206207
// Disabled behind disableUnstableRenderSubtreeIntoContainer

0 commit comments

Comments
 (0)