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

Update entry point exports (#21488)

The following APIs have been added to the `react` stable entry point: * `SuspenseList` * `startTransition` * `unstable_createMutableSource` * `unstable_useMutableSource` * `useDeferredValue` * `useTransition` The following APIs have been added or removed from the `react-dom` stable entry point: * `createRoot` * `unstable_createPortal` (removed) The following APIs have been added to the `react-is` stable entry point: * `SuspenseList` * `isSuspenseList` The following feature flags have been changed from experimental to true: * `enableLazyElements` * `enableSelectiveHydration` * `enableSuspenseServerRenderer`

Brian Vaughn committed May 12, 2021 at 11:28 UTC 2bf4805e4bd63dab45cd7f5e1ad32ef8fed3f6ab
92 files changed +572 -966
packages/create-subscription/src/__tests__/createSubscription-test.js
+2 -4
@@ -268,7 +268,6 @@ describe('createSubscription', () => {
268 expect(Scheduler).toFlushAndYield(['b-1']);
269 });
270
271 - // @gate experimental || !enableSyncDefaultUpdates
271 it('should ignore values emitted by a new subscribable until the commit phase', () => {
272 const log = [];
273
@@ -327,7 +326,7 @@ describe('createSubscription', () => {
326
327 // Start React update, but don't finish
328 if (gate(flags => flags.enableSyncDefaultUpdates)) {
330 - React.unstable_startTransition(() => {
329 + React.startTransition(() => {
330 ReactNoop.render(<Parent observed={observableB} />);
331 });
332 } else {
@@ -362,7 +361,6 @@ describe('createSubscription', () => {
361 ]);
362 });
363
365 - // @gate experimental || !enableSyncDefaultUpdates
364 it('should not drop values emitted between updates', () => {
365 const log = [];
366
@@ -421,7 +419,7 @@ describe('createSubscription', () => {
419
420 // Start React update, but don't finish
421 if (gate(flags => flags.enableSyncDefaultUpdates)) {
424 - React.unstable_startTransition(() => {
422 + React.startTransition(() => {
423 ReactNoop.render(<Parent observed={observableB} />);
424 });
425 } else {
packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.js
+38 -39
@@ -366,10 +366,9 @@ describe('ReactHooksInspectionIntegration', () => {
366 ]);
367 });
368
369 - // @gate experimental
369 it('should support composite useTransition hook', () => {
370 function Foo(props) {
372 - React.unstable_useTransition();
371 + React.useTransition();
372 const memoizedValue = React.useMemo(() => 'hello', []);
373 return <div>{memoizedValue}</div>;
374 }
@@ -394,10 +393,9 @@ describe('ReactHooksInspectionIntegration', () => {
393 ]);
394 });
395
397 - // @gate experimental
396 it('should support composite useDeferredValue hook', () => {
397 function Foo(props) {
400 - React.unstable_useDeferredValue('abc', {
398 + React.useDeferredValue('abc', {
399 timeoutMs: 500,
400 });
401 const [state] = React.useState(() => 'hello', []);
@@ -424,7 +422,6 @@ describe('ReactHooksInspectionIntegration', () => {
422 ]);
423 });
424
427 - // @gate experimental
425 it('should support composite useOpaqueIdentifier hook', () => {
426 function Foo(props) {
427 const id = React.unstable_useOpaqueIdentifier();
@@ -452,7 +449,6 @@ describe('ReactHooksInspectionIntegration', () => {
449 });
450 });
451
455 - // @gate experimental
452 it('should support composite useOpaqueIdentifier hook in concurrent mode', () => {
453 function Foo(props) {
454 const id = React.unstable_useOpaqueIdentifier();
@@ -846,37 +842,40 @@ describe('ReactHooksInspectionIntegration', () => {
842 ]);
843 });
844
849 - if (__EXPERIMENTAL__) {
850 - it('should support composite useMutableSource hook', () => {
851 - const mutableSource = React.unstable_createMutableSource({}, () => 1);
852 - function Foo(props) {
853 - React.unstable_useMutableSource(
854 - mutableSource,
855 - () => 'snapshot',
856 - () => {},
857 - );
858 - React.useMemo(() => 'memo', []);
859 - return <div />;
860 - }
861 - const renderer = ReactTestRenderer.create(<Foo />);
862 - const childFiber = renderer.root.findByType(Foo)._currentFiber();
863 - const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
864 - expect(tree).toEqual([
865 - {
866 - id: 0,
867 - isStateEditable: false,
868 - name: 'MutableSource',
869 - value: 'snapshot',
870 - subHooks: [],
871 - },
872 - {
873 - id: 1,
874 - isStateEditable: false,
875 - name: 'Memo',
876 - value: 'memo',
877 - subHooks: [],
878 - },
879 - ]);
880 - });
881 - }
845 + it('should support composite useMutableSource hook', () => {
846 + const createMutableSource =
847 + React.createMutableSource || React.unstable_createMutableSource;
848 + const useMutableSource =
849 + React.useMutableSource || React.unstable_useMutableSource;
850 +
851 + const mutableSource = createMutableSource({}, () => 1);
852 + function Foo(props) {
853 + useMutableSource(
854 + mutableSource,
855 + () => 'snapshot',
856 + () => {},
857 + );
858 + React.useMemo(() => 'memo', []);
859 + return <div />;
860 + }
861 + const renderer = ReactTestRenderer.create(<Foo />);
862 + const childFiber = renderer.root.findByType(Foo)._currentFiber();
863 + const tree = ReactDebugTools.inspectHooksOfFiber(childFiber);
864 + expect(tree).toEqual([
865 + {
866 + id: 0,
867 + isStateEditable: false,
868 + name: 'MutableSource',
869 + value: 'snapshot',
870 + subHooks: [],
871 + },
872 + {
873 + id: 1,
874 + isStateEditable: false,
875 + name: 'Memo',
876 + value: 'memo',
877 + subHooks: [],
878 + },
879 + ]);
880 + });
881 });
packages/react-devtools-core/src/standalone.js
+1 -1
@@ -12,7 +12,7 @@ import {
12 // $FlowFixMe Flow does not yet know about flushSync()
13 flushSync,
14 // $FlowFixMe Flow does not yet know about createRoot()
15 - unstable_createRoot as createRoot,
15 + createRoot,
16 } from 'react-dom';
17 import Bridge from 'react-devtools-shared/src/bridge';
18 import Store from 'react-devtools-shared/src/devtools/store';
packages/react-devtools-extensions/src/main.js
+1 -1
@@ -1,7 +1,7 @@
1 /* global chrome */
2
3 import {createElement} from 'react';
4 -import {unstable_createRoot as createRoot, flushSync} from 'react-dom';
4 +import {createRoot, flushSync} from 'react-dom';
5 import Bridge from 'react-devtools-shared/src/bridge';
6 import Store from 'react-devtools-shared/src/devtools/store';
7 import {getBrowserName, getBrowserTheme} from './utils';
packages/react-devtools-scheduling-profiler/src/hooks.js
+3 -1
@@ -8,9 +8,11 @@
8 */
9
10 import {
11 + // $FlowFixMe
12 unstable_createMutableSource as createMutableSource,
12 - unstable_useMutableSource as useMutableSource,
13 useLayoutEffect,
14 + // $FlowFixMe
15 + unstable_useMutableSource as useMutableSource,
16 } from 'react';
17
18 import {
packages/react-devtools-scheduling-profiler/src/import-worker/__tests__/preprocessData-test.internal.js
+1 -1
@@ -382,7 +382,7 @@ describe(preprocessData, () => {
382 });
383 });
384
385 - // @gate experimental && enableSchedulingProfiler
385 + // @gate enableSchedulingProfiler
386 it('should process a sample createRoot render sequence', () => {
387 function App() {
388 const [didMount, setDidMount] = React.useState(false);
packages/react-devtools-scheduling-profiler/src/index.js
+1 -1
@@ -11,7 +11,7 @@ import 'regenerator-runtime/runtime';
11
12 import * as React from 'react';
13 // $FlowFixMe Flow does not yet know about createRoot()
14 -import {unstable_createRoot as createRoot} from 'react-dom';
14 +import {createRoot} from 'react-dom';
15 import nullthrows from 'nullthrows';
16 import App from './App';
17
packages/react-devtools-shared/src/__tests__/profilingCommitTreeBuilder-test.js
+2 -2
@@ -149,7 +149,7 @@ describe('commit tree', () => {
149
150 it('should support Lazy components (createRoot)', async () => {
151 const container = document.createElement('div');
152 - const root = ReactDOM.unstable_createRoot(container);
152 + const root = ReactDOM.createRoot(container);
153
154 utils.act(() => store.profilerStore.startProfiling());
155 utils.act(() => root.render(<App renderChildren={true} />));
@@ -226,7 +226,7 @@ describe('commit tree', () => {
226
227 it('should support Lazy components that are unmounted before resolving (createRoot)', async () => {
228 const container = document.createElement('div');
229 - const root = ReactDOM.unstable_createRoot(container);
229 + const root = ReactDOM.createRoot(container);
230
231 utils.act(() => store.profilerStore.startProfiling());
232 utils.act(() => root.render(<App renderChildren={true} />));
packages/react-devtools-shared/src/__tests__/profilingHostRoot-test.js
+2 -2
@@ -89,7 +89,7 @@ describe('profiling HostRoot', () => {
89 utils.act(() => store.profilerStore.startProfiling());
90 utils.act(() => {
91 const container = document.createElement('div');
92 - const root = ReactDOM.unstable_createRoot(container);
92 + const root = ReactDOM.createRoot(container);
93 root.render(<App />);
94 });
95 utils.act(() => store.profilerStore.stopProfiling());
@@ -122,7 +122,7 @@ describe('profiling HostRoot', () => {
122 }
123
124 const container = document.createElement('div');
125 - const root = ReactDOM.unstable_createRoot(container);
125 + const root = ReactDOM.createRoot(container);
126
127 utils.act(() => store.profilerStore.startProfiling());
128 utils.act(() => root.render(<App />));
packages/react-devtools-shared/src/__tests__/store-test.js
+5 -5
@@ -356,18 +356,18 @@ describe('Store', () => {
356 };
357 const Wrapper = ({shouldSuspense}) => (
358 <React.Fragment>
359 - <React.unstable_SuspenseList revealOrder="forwards" tail="collapsed">
359 + <React.SuspenseList revealOrder="forwards" tail="collapsed">
360 <Component key="A" />
361 <React.Suspense fallback={<Loading />}>
362 {shouldSuspense ? <SuspendingComponent /> : <Component key="B" />}
363 </React.Suspense>
364 <Component key="C" />
365 - </React.unstable_SuspenseList>
365 + </React.SuspenseList>
366 </React.Fragment>
367 );
368
369 const container = document.createElement('div');
370 - const root = ReactDOM.unstable_createRoot(container);
370 + const root = ReactDOM.createRoot(container);
371 act(() => {
372 root.render(<Wrapper shouldSuspense={true} />);
373 });
@@ -984,7 +984,7 @@ describe('Store', () => {
984
985 it('should support Lazy components in (createRoot)', async () => {
986 const container = document.createElement('div');
987 - const root = ReactDOM.unstable_createRoot(container);
987 + const root = ReactDOM.createRoot(container);
988
989 // Render once to start fetching the lazy component
990 act(() => root.render(<App renderChildren={true} />));
@@ -1020,7 +1020,7 @@ describe('Store', () => {
1020
1021 it('should support Lazy components that are unmounted before they finish loading in (createRoot)', async () => {
1022 const container = document.createElement('div');
1023 - const root = ReactDOM.unstable_createRoot(container);
1023 + const root = ReactDOM.createRoot(container);
1024
1025 // Render once to start fetching the lazy component
1026 act(() => root.render(<App renderChildren={true} />));
packages/react-devtools-shared/src/__tests__/storeStressTestConcurrent-test.js
+18 -18
@@ -67,7 +67,7 @@ describe('StoreStressConcurrent', () => {
67 // 1. Render a normal version of [a, b, c, d, e].
68 let container = document.createElement('div');
69 // $FlowFixMe
70 - let root = ReactDOM.unstable_createRoot(container);
70 + let root = ReactDOM.createRoot(container);
71 act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>));
72 expect(store).toMatchInlineSnapshot(
73 `
@@ -151,7 +151,7 @@ describe('StoreStressConcurrent', () => {
151 // Ensure fresh mount.
152 container = document.createElement('div');
153 // $FlowFixMe
154 - root = ReactDOM.unstable_createRoot(container);
154 + root = ReactDOM.createRoot(container);
155
156 // Verify mounting 'abcde'.
157 act(() => root.render(<Parent>{cases[i]}</Parent>));
@@ -181,7 +181,7 @@ describe('StoreStressConcurrent', () => {
181 // There'll be no unmounting until the very end.
182 container = document.createElement('div');
183 // $FlowFixMe
184 - root = ReactDOM.unstable_createRoot(container);
184 + root = ReactDOM.createRoot(container);
185 for (let i = 0; i < cases.length; i++) {
186 // Verify mounting 'abcde'.
187 act(() => root.render(<Parent>{cases[i]}</Parent>));
@@ -247,7 +247,7 @@ describe('StoreStressConcurrent', () => {
247 const snapshots = [];
248 let container = document.createElement('div');
249 // $FlowFixMe
250 - let root = ReactDOM.unstable_createRoot(container);
250 + let root = ReactDOM.createRoot(container);
251 for (let i = 0; i < steps.length; i++) {
252 act(() => root.render(<Root>{steps[i]}</Root>));
253 // We snapshot each step once so it doesn't regress.
@@ -320,7 +320,7 @@ describe('StoreStressConcurrent', () => {
320 for (let j = 0; j < steps.length; j++) {
321 container = document.createElement('div');
322 // $FlowFixMe
323 - root = ReactDOM.unstable_createRoot(container);
323 + root = ReactDOM.createRoot(container);
324 act(() => root.render(<Root>{steps[i]}</Root>));
325 expect(print(store)).toMatch(snapshots[i]);
326 act(() => root.render(<Root>{steps[j]}</Root>));
@@ -337,7 +337,7 @@ describe('StoreStressConcurrent', () => {
337 for (let j = 0; j < steps.length; j++) {
338 container = document.createElement('div');
339 // $FlowFixMe
340 - root = ReactDOM.unstable_createRoot(container);
340 + root = ReactDOM.createRoot(container);
341 act(() =>
342 root.render(
343 <Root>
@@ -409,7 +409,7 @@ describe('StoreStressConcurrent', () => {
409 const snapshots = [];
410 let container = document.createElement('div');
411 // $FlowFixMe
412 - let root = ReactDOM.unstable_createRoot(container);
412 + let root = ReactDOM.createRoot(container);
413 for (let i = 0; i < steps.length; i++) {
414 act(() =>
415 root.render(
@@ -536,7 +536,7 @@ describe('StoreStressConcurrent', () => {
536 // Always start with a fresh container and steps[i].
537 container = document.createElement('div');
538 // $FlowFixMe
539 - root = ReactDOM.unstable_createRoot(container);
539 + root = ReactDOM.createRoot(container);
540 act(() =>
541 root.render(
542 <Root>
@@ -582,7 +582,7 @@ describe('StoreStressConcurrent', () => {
582 // Always start with a fresh container and steps[i].
583 container = document.createElement('div');
584 // $FlowFixMe
585 - root = ReactDOM.unstable_createRoot(container);
585 + root = ReactDOM.createRoot(container);
586 act(() =>
587 root.render(
588 <Root>
@@ -640,7 +640,7 @@ describe('StoreStressConcurrent', () => {
640 // Always start with a fresh container and steps[i].
641 container = document.createElement('div');
642 // $FlowFixMe
643 - root = ReactDOM.unstable_createRoot(container);
643 + root = ReactDOM.createRoot(container);
644 act(() =>
645 root.render(
646 <Root>
@@ -690,7 +690,7 @@ describe('StoreStressConcurrent', () => {
690 // Always start with a fresh container and steps[i].
691 container = document.createElement('div');
692 // $FlowFixMe
693 - root = ReactDOM.unstable_createRoot(container);
693 + root = ReactDOM.createRoot(container);
694 act(() =>
695 root.render(
696 <Root>
@@ -744,7 +744,7 @@ describe('StoreStressConcurrent', () => {
744 // Always start with a fresh container and steps[i].
745 container = document.createElement('div');
746 // $FlowFixMe
747 - root = ReactDOM.unstable_createRoot(container);
747 + root = ReactDOM.createRoot(container);
748 act(() =>
749 root.render(
750 <Root>
@@ -898,7 +898,7 @@ describe('StoreStressConcurrent', () => {
898 const snapshots = [];
899 let container = document.createElement('div');
900 // $FlowFixMe
901 - let root = ReactDOM.unstable_createRoot(container);
901 + let root = ReactDOM.createRoot(container);
902 for (let i = 0; i < steps.length; i++) {
903 act(() =>
904 root.render(
@@ -1055,7 +1055,7 @@ describe('StoreStressConcurrent', () => {
1055 // Always start with a fresh container and steps[i].
1056 container = document.createElement('div');
1057 // $FlowFixMe
1058 - root = ReactDOM.unstable_createRoot(container);
1058 + root = ReactDOM.createRoot(container);
1059 act(() =>
1060 root.render(
1061 <Root>
@@ -1107,7 +1107,7 @@ describe('StoreStressConcurrent', () => {
1107 // Always start with a fresh container and steps[i].
1108 container = document.createElement('div');
1109 // $FlowFixMe
1110 - root = ReactDOM.unstable_createRoot(container);
1110 + root = ReactDOM.createRoot(container);
1111 act(() =>
1112 root.render(
1113 <Root>
@@ -1174,7 +1174,7 @@ describe('StoreStressConcurrent', () => {
1174 // Always start with a fresh container and steps[i].
1175 container = document.createElement('div');
1176 // $FlowFixMe
1177 - root = ReactDOM.unstable_createRoot(container);
1177 + root = ReactDOM.createRoot(container);
1178 act(() =>
1179 root.render(
1180 <Root>
@@ -1226,7 +1226,7 @@ describe('StoreStressConcurrent', () => {
1226 // Always start with a fresh container and steps[i].
1227 container = document.createElement('div');
1228 // $FlowFixMe
1229 - root = ReactDOM.unstable_createRoot(container);
1229 + root = ReactDOM.createRoot(container);
1230 act(() =>
1231 root.render(
1232 <Root>
@@ -1278,7 +1278,7 @@ describe('StoreStressConcurrent', () => {
1278 // Always start with a fresh container and steps[i].
1279 container = document.createElement('div');
1280 // $FlowFixMe
1281 - root = ReactDOM.unstable_createRoot(container);
1281 + root = ReactDOM.createRoot(container);
1282 act(() =>
1283 root.render(
1284 <Root>
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementContext.js
+1 -1
@@ -10,7 +10,7 @@
10 import * as React from 'react';
11 import {
12 createContext,
13 - unstable_startTransition as startTransition,
13 + startTransition,
14 unstable_useCacheRefresh as useCacheRefresh,
15 useCallback,
16 useContext,
packages/react-devtools-shared/src/devtools/views/Components/InspectedElementErrorsAndWarningsTree.js
+1 -1
@@ -11,7 +11,7 @@ import * as React from 'react';
11 import {
12 useContext,
13 unstable_useCacheRefresh as useCacheRefresh,
14 - unstable_useTransition as useTransition,
14 + useTransition,
15 } from 'react';
16 import Button from '../Button';
17 import ButtonIcon from '../ButtonIcon';
packages/react-devtools-shared/src/devtools/views/Components/KeyValue.js
+1 -6
@@ -8,12 +8,7 @@
8 */
9
10 import * as React from 'react';
11 -import {
12 - unstable_useTransition as useTransition,
13 - useContext,
14 - useRef,
15 - useState,
16 -} from 'react';
11 +import {useTransition, useContext, useRef, useState} from 'react';
12 import EditableName from './EditableName';
13 import EditableValue from './EditableValue';
14 import NewArrayValue from './NewArrayValue';
packages/react-devtools-shared/src/devtools/views/Components/TreeContext.js
+1 -1
@@ -34,7 +34,7 @@ import {
34 useMemo,
35 useReducer,
36 useRef,
37 - unstable_startTransition as startTransition,
37 + startTransition,
38 } from 'react';
39 import {createRegExp} from '../utils';
40 import {BridgeContext, StoreContext} from '../context';
packages/react-devtools-shared/src/devtools/views/ErrorBoundary/cache.js
+2 -2
@@ -10,7 +10,7 @@
10 import type {Wakeable} from 'shared/ReactTypes';
11 import type {GitHubIssue} from './githubAPI';
12
13 -import {unstable_getCacheForType} from 'react';
13 +import {unstable_getCacheForType as getCacheForType} from 'react';
14 import {searchGitHubIssues} from './githubAPI';
15
16 const API_TIMEOUT = 3000;
@@ -55,7 +55,7 @@ function createMap(): GitHubIssueMap {
55 }
56
57 function getRecordMap(): Map<string, Record<GitHubIssue>> {
58 - return unstable_getCacheForType(createMap);
58 + return getCacheForType(createMap);
59 }
60
61 export function findGitHubIssue(errorMessage: string): GitHubIssue | null {
packages/react-devtools-shared/src/inspectedElementCache.js
+3 -3
@@ -8,8 +8,8 @@
8 */
9
10 import {
11 - unstable_getCacheForType,
12 - unstable_startTransition as startTransition,
11 + unstable_getCacheForType as getCacheForType,
12 + startTransition,
13 } from 'react';
14 import Store from './devtools/store';
15 import {inspectElement as inspectElementMutableSource} from './inspectedElementMutableSource';
@@ -60,7 +60,7 @@ function createMap(): InspectedElementMap {
60 }
61
62 function getRecordMap(): WeakMap<Element, Record<InspectedElementFrontend>> {
63 - return unstable_getCacheForType(createMap);
63 + return getCacheForType(createMap);
64 }
65
66 function createCacheSeed(
packages/react-devtools-shell/src/app/SuspenseTree/index.js
+1 -6
@@ -8,12 +8,7 @@
8 */
9
10 import * as React from 'react';
11 -import {
12 - Fragment,
13 - Suspense,
14 - unstable_SuspenseList as SuspenseList,
15 - useState,
16 -} from 'react';
11 +import {Fragment, Suspense, SuspenseList, useState} from 'react';
12
13 function SuspenseTree() {
14 return (
packages/react-devtools-shell/src/app/index.js
+1 -1
@@ -5,7 +5,7 @@
5 import {createElement} from 'react';
6 import {
7 // $FlowFixMe Flow does not yet know about createRoot()
8 - unstable_createRoot as createRoot,
8 + createRoot,
9 } from 'react-dom';
10 import DeeplyNestedComponents from './DeeplyNestedComponents';
11 import Iframe from './Iframe';
packages/react-devtools-shell/src/devtools.js
+1 -1
@@ -2,7 +2,7 @@
2
3 import {createElement} from 'react';
4 // $FlowFixMe Flow does not yet know about createRoot()
5 -import {unstable_createRoot as createRoot} from 'react-dom';
5 +import {createRoot} from 'react-dom';
6 import {
7 activate as activateBackend,
8 initialize as initializeBackend,
packages/react-dom/index.classic.fb.js
+10 -11
@@ -19,22 +19,21 @@ Object.assign((__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: any), {
19 });
20
21 export {
22 - createPortal,
23 - unstable_batchedUpdates,
24 - flushSync,
22 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
26 - version,
23 + createPortal,
24 + createRoot,
25 + createRoot as unstable_createRoot, // TODO Remove once callsites use createRoot
26 findDOMNode,
27 + flushSync,
28 hydrate,
29 render,
30 unmountComponentAtNode,
31 - createRoot,
32 - createRoot as unstable_createRoot,
33 - unstable_flushControlled,
34 - unstable_scheduleHydration,
35 - unstable_runWithPriority,
36 - unstable_renderSubtreeIntoContainer,
37 - unstable_createPortal,
31 + unstable_batchedUpdates,
32 unstable_createEventHandle,
33 + unstable_flushControlled,
34 unstable_isNewReconciler,
35 + unstable_renderSubtreeIntoContainer,
36 + unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
37 + unstable_scheduleHydration,
38 + version,
39 } from './src/client/ReactDOM';
packages/react-dom/index.experimental.js
+7 -15
@@ -8,26 +8,18 @@
8 */
9
10 export {
11 - createPortal,
12 - unstable_batchedUpdates,
13 - flushSync,
11 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
15 - version,
16 - // Disabled behind disableLegacyReactDOMAPIs
12 + createPortal,
13 + createRoot,
14 findDOMNode,
15 + flushSync,
16 hydrate,
17 render,
18 unmountComponentAtNode,
21 - // exposeConcurrentModeAPIs
22 - createRoot as unstable_createRoot,
19 + unstable_batchedUpdates,
20 unstable_flushControlled,
24 - unstable_scheduleHydration,
25 - // DO NOT USE: Temporarily exposing this to migrate off of Scheduler.runWithPriority.
26 - unstable_runWithPriority,
27 - // Disabled behind disableUnstableRenderSubtreeIntoContainer
21 unstable_renderSubtreeIntoContainer,
29 - // Disabled behind disableUnstableCreatePortal
30 - // Temporary alias since we already shipped React 16 RC with it.
31 - // TODO: remove in React 18.
32 - unstable_createPortal,
22 + unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
23 + unstable_scheduleHydration,
24 + version,
25 } from './src/client/ReactDOM';
packages/react-dom/index.js
+10 -11
@@ -10,22 +10,21 @@
10 // Export all exports so that they're available in tests.
11 // We can't use export * from in Flow for some reason.
12 export {
13 - createPortal,
14 - unstable_batchedUpdates,
15 - flushSync,
13 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
17 - version,
14 + createPortal,
15 + createRoot,
16 + createRoot as unstable_createRoot,
17 findDOMNode,
18 + flushSync,
19 hydrate,
20 render,
21 unmountComponentAtNode,
22 - createRoot,
23 - createRoot as unstable_createRoot,
24 - unstable_flushControlled,
25 - unstable_scheduleHydration,
26 - unstable_runWithPriority,
27 - unstable_renderSubtreeIntoContainer,
28 - unstable_createPortal,
22 + unstable_batchedUpdates,
23 unstable_createEventHandle,
24 + unstable_flushControlled,
25 unstable_isNewReconciler,
26 + unstable_renderSubtreeIntoContainer,
27 + unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
28 + unstable_scheduleHydration,
29 + version,
30 } from './src/client/ReactDOM';
packages/react-dom/index.modern.fb.js
+8 -8
@@ -8,16 +8,16 @@
8 */
9
10 export {
11 - createPortal,
12 - unstable_batchedUpdates,
13 - flushSync,
11 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
15 - version,
12 + createPortal,
13 createRoot,
17 - createRoot as unstable_createRoot,
18 - unstable_flushControlled,
19 - unstable_scheduleHydration,
20 - unstable_runWithPriority,
14 + createRoot as unstable_createRoot, // TODO Remove once callsites use createRoot
15 + flushSync,
16 + unstable_batchedUpdates,
17 unstable_createEventHandle,
18 + unstable_flushControlled,
19 unstable_isNewReconciler,
20 + unstable_runWithPriority, // DO NOT USE: Temporarily exposed to migrate off of Scheduler.runWithPriority.
21 + unstable_scheduleHydration,
22 + version,
23 } from './src/client/ReactDOM';
packages/react-dom/index.stable.js
+5 -7
@@ -8,17 +8,15 @@
8 */
9
10 export {
11 - createPortal,
12 - unstable_batchedUpdates,
13 - flushSync,
11 __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
15 - version,
12 + createPortal,
13 + createRoot,
14 findDOMNode,
15 + flushSync,
16 hydrate,
17 render,
18 unmountComponentAtNode,
19 + unstable_batchedUpdates,
20 unstable_renderSubtreeIntoContainer,
21 - // Temporary alias since we already shipped React 16 RC with it.
22 - // TODO: remove in React 18.
23 - unstable_createPortal,
21 + version,
22 } from './src/client/ReactDOM';
packages/react-dom/src/__tests__/ReactDOMFiber-test.js
-28
@@ -246,34 +246,6 @@ describe('ReactDOMFiber', () => {
246 expect(container.innerHTML).toBe('');
247 });
248
249 - // TODO: remove in React 18
250 - if (!__EXPERIMENTAL__) {
251 - it('should support unstable_createPortal alias', () => {
252 - const portalContainer = document.createElement('div');
253 -
254 - expect(() =>
255 - ReactDOM.render(
256 - <div>
257 - {ReactDOM.unstable_createPortal(<div>portal</div>, portalContainer)}
258 - </div>,
259 - container,
260 - ),
261 - ).toWarnDev(
262 - 'The ReactDOM.unstable_createPortal() alias has been deprecated, ' +
263 - 'and will be removed in React 18+. Update your code to use ' +
264 - 'ReactDOM.createPortal() instead. It has the exact same API, ' +
265 - 'but without the "unstable_" prefix.',
266 - {withoutStack: true},
267 - );
268 - expect(portalContainer.innerHTML).toBe('<div>portal</div>');
269 - expect(container.innerHTML).toBe('<div></div>');
270 -
271 - ReactDOM.unmountComponentAtNode(container);
272 - expect(portalContainer.innerHTML).toBe('');
273 - expect(container.innerHTML).toBe('');
274 - });
275 - }
276 -
249 it('should render many portals', () => {
250 const portalContainer1 = document.createElement('div');
251 const portalContainer2 = document.createElement('div');
packages/react-dom/src/__tests__/ReactDOMFiberAsync-test.js
+11 -20
@@ -148,7 +148,6 @@ describe('ReactDOMFiberAsync', () => {
148 });
149
150 describe('concurrent mode', () => {
151 - // @gate experimental
151 it('does not perform deferred updates synchronously', () => {
152 const inputRef = React.createRef();
153 const asyncValueRef = React.createRef();
@@ -185,7 +184,7 @@ describe('ReactDOMFiberAsync', () => {
184 );
185 }
186 }
188 - const root = ReactDOM.unstable_createRoot(container);
187 + const root = ReactDOM.createRoot(container);
188 root.render(<Counter />);
189 Scheduler.unstable_flushAll();
190 expect(asyncValueRef.current.textContent).toBe('');
@@ -204,9 +203,8 @@ describe('ReactDOMFiberAsync', () => {
203 expect(syncValueRef.current.textContent).toBe('hello');
204 });
205
207 - // @gate experimental
206 it('top-level updates are concurrent', () => {
209 - const root = ReactDOM.unstable_createRoot(container);
207 + const root = ReactDOM.createRoot(container);
208 root.render(<div>Hi</div>);
209 expect(container.textContent).toEqual('');
210 Scheduler.unstable_flushAll();
@@ -218,7 +216,6 @@ describe('ReactDOMFiberAsync', () => {
216 expect(container.textContent).toEqual('Bye');
217 });
218
221 - // @gate experimental
219 it('deep updates (setState) are concurrent', () => {
220 let instance;
221 class Component extends React.Component {
@@ -229,7 +226,7 @@ describe('ReactDOMFiberAsync', () => {
226 }
227 }
228
232 - const root = ReactDOM.unstable_createRoot(container);
229 + const root = ReactDOM.createRoot(container);
230 root.render(<Component />);
231 expect(container.textContent).toEqual('');
232 Scheduler.unstable_flushAll();
@@ -241,7 +238,6 @@ describe('ReactDOMFiberAsync', () => {
238 expect(container.textContent).toEqual('1');
239 });
240
244 - // @gate experimental
241 it('flushSync flushes updates before end of the tick', () => {
242 const ops = [];
243 let instance;
@@ -260,7 +256,7 @@ describe('ReactDOMFiberAsync', () => {
256 }
257 }
258
263 - const root = ReactDOM.unstable_createRoot(container);
259 + const root = ReactDOM.createRoot(container);
260 root.render(<Component />);
261 Scheduler.unstable_flushAll();
262
@@ -302,7 +298,7 @@ describe('ReactDOMFiberAsync', () => {
298 return this.state.counter;
299 }
300 }
305 - const root = ReactDOM.unstable_createRoot(container);
301 + const root = ReactDOM.createRoot(container);
302 root.render(<Counter />);
303 Scheduler.unstable_flushAll();
304 expect(container.textContent).toEqual('0');
@@ -385,7 +381,6 @@ describe('ReactDOMFiberAsync', () => {
381 expect(returnValue).toBe(undefined);
382 });
383
388 - // @gate experimental
384 it('ignores discrete events on a pending removed element', async () => {
385 const disableButtonRef = React.createRef();
386 const submitButtonRef = React.createRef();
@@ -406,7 +401,7 @@ describe('ReactDOMFiberAsync', () => {
401 );
402 }
403
409 - const root = ReactDOM.unstable_createRoot(container);
404 + const root = ReactDOM.createRoot(container);
405 await act(async () => {
406 root.render(<Form />);
407 });
@@ -426,7 +421,6 @@ describe('ReactDOMFiberAsync', () => {
421 expect(submitButton.current).toBe(undefined);
422 });
423
429 - // @gate experimental
424 it('ignores discrete events on a pending removed event listener', async () => {
425 const disableButtonRef = React.createRef();
426 const submitButtonRef = React.createRef();
@@ -458,7 +452,7 @@ describe('ReactDOMFiberAsync', () => {
452 );
453 }
454
461 - const root = ReactDOM.unstable_createRoot(container);
455 + const root = ReactDOM.createRoot(container);
456 await act(async () => {
457 root.render(<Form />);
458 });
@@ -491,7 +485,6 @@ describe('ReactDOMFiberAsync', () => {
485 expect(formSubmitted).toBe(false);
486 });
487
494 - // @gate experimental
488 it('uses the newest discrete events on a pending changed event listener', async () => {
489 const enableButtonRef = React.createRef();
490 const submitButtonRef = React.createRef();
@@ -518,7 +511,7 @@ describe('ReactDOMFiberAsync', () => {
511 );
512 }
513
521 - const root = ReactDOM.unstable_createRoot(container);
514 + const root = ReactDOM.createRoot(container);
515 await act(async () => {
516 root.render(<Form />);
517 });
@@ -582,9 +575,8 @@ describe('ReactDOMFiberAsync', () => {
575 expect(containerC.textContent).toEqual('Finished');
576 });
577
585 - // @gate experimental
578 it('updates flush without yielding in the next event', () => {
587 - const root = ReactDOM.unstable_createRoot(container);
579 + const root = ReactDOM.createRoot(container);
580
581 function Text(props) {
582 Scheduler.unstable_yieldValue(props.text);
@@ -607,7 +599,6 @@ describe('ReactDOMFiberAsync', () => {
599 expect(container.textContent).toEqual('ABC');
600 });
601
610 - // @gate experimental
602 it('unmounted roots should never clear newer root content from a container', () => {
603 const ref = React.createRef();
604
@@ -630,7 +621,7 @@ describe('ReactDOMFiberAsync', () => {
621 return <button ref={ref}>new</button>;
622 }
623
633 - const oldRoot = ReactDOM.unstable_createRoot(container);
624 + const oldRoot = ReactDOM.createRoot(container);
625 act(() => {
626 oldRoot.render(<OldApp />);
627 });
@@ -642,7 +633,7 @@ describe('ReactDOMFiberAsync', () => {
633 expect(container.textContent).toBe('');
634
635 // We can now render a new one.
645 - const newRoot = ReactDOM.unstable_createRoot(container);
636 + const newRoot = ReactDOM.createRoot(container);
637 ReactDOM.flushSync(() => {
638 newRoot.render(<NewApp />);
639 });
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js
+8 -8
@@ -38,7 +38,7 @@ describe('ReactDOMFizzServer', () => {
38 }
39 Stream = require('stream');
40 Suspense = React.Suspense;
41 - SuspenseList = React.unstable_SuspenseList;
41 + SuspenseList = React.SuspenseList;
42 PropTypes = require('prop-types');
43
44 textCache = new Map();
@@ -313,7 +313,7 @@ describe('ReactDOMFizzServer', () => {
313 expect(loggedErrors).toEqual([]);
314
315 // Attempt to hydrate the content.
316 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
316 + const root = ReactDOM.createRoot(container, {hydrate: true});
317 root.render(<App isClient={true} />);
318 Scheduler.unstable_flushAll();
319
@@ -405,7 +405,7 @@ describe('ReactDOMFizzServer', () => {
405 expect(loggedErrors).toEqual([]);
406
407 // Attempt to hydrate the content.
408 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
408 + const root = ReactDOM.createRoot(container, {hydrate: true});
409 root.render(<App isClient={true} />);
410 Scheduler.unstable_flushAll();
411
@@ -481,7 +481,7 @@ describe('ReactDOMFizzServer', () => {
481 expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);
482
483 // Attempt to hydrate the content.
484 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
484 + const root = ReactDOM.createRoot(container, {hydrate: true});
485 root.render(<App />);
486 Scheduler.unstable_flushAll();
487
@@ -563,7 +563,7 @@ describe('ReactDOMFizzServer', () => {
563 expect(loggedErrors).toEqual([]);
564
565 // Attempt to hydrate the content.
566 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
566 + const root = ReactDOM.createRoot(container, {hydrate: true});
567 root.render(<App />);
568 Scheduler.unstable_flushAll();
569
@@ -635,7 +635,7 @@ describe('ReactDOMFizzServer', () => {
635 startWriting();
636 });
637
638 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
638 + const root = ReactDOM.createRoot(container, {hydrate: true});
639 root.render(<App showMore={false} />);
640 Scheduler.unstable_flushAll();
641
@@ -703,7 +703,7 @@ describe('ReactDOMFizzServer', () => {
703 // We're still showing a fallback.
704
705 // Attempt to hydrate the content.
706 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
706 + const root = ReactDOM.createRoot(container, {hydrate: true});
707 root.render(<App />);
708 Scheduler.unstable_flushAll();
709
@@ -1294,7 +1294,7 @@ describe('ReactDOMFizzServer', () => {
1294 // We're still showing a fallback.
1295
1296 // Attempt to hydrate the content.
1297 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
1297 + const root = ReactDOM.createRoot(container, {hydrate: true});
1298 root.render(<App isClient={true} />);
1299 Scheduler.unstable_flushAll();
1300
packages/react-dom/src/__tests__/ReactDOMHooks-test.js
+1 -2
@@ -107,7 +107,6 @@ describe('ReactDOMHooks', () => {
107 expect(labelRef.current.innerHTML).toBe('abc');
108 });
109
110 - // @gate experimental
110 it('should not bail out when an update is scheduled from within an event handler in Concurrent Mode', async () => {
111 const {createRef, useCallback, useState} = React;
112
@@ -128,7 +127,7 @@ describe('ReactDOMHooks', () => {
127 const inputRef = createRef();
128 const labelRef = createRef();
129
131 - const root = ReactDOM.unstable_createRoot(container);
130 + const root = ReactDOM.createRoot(container);
131 root.render(<Example inputRef={inputRef} labelRef={labelRef} />);
132
133 Scheduler.unstable_flushAll();
packages/react-dom/src/__tests__/ReactDOMNativeEventHeuristic-test.js
+8 -16
@@ -42,7 +42,6 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
42 }
43 }
44
45 - // @gate experimental
45 it('ignores discrete events on a pending removed element', async () => {
46 const disableButtonRef = React.createRef();
47 const submitButtonRef = React.createRef();
@@ -66,7 +65,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
65 );
66 }
67
69 - const root = ReactDOM.unstable_createRoot(container);
68 + const root = ReactDOM.createRoot(container);
69 await act(() => {
70 root.render(<Form />);
71 });
@@ -88,7 +87,6 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
87 // We'll assume that the browser won't let the user click it.
88 });
89
91 - // @gate experimental
90 it('ignores discrete events on a pending removed event listener', async () => {
91 const disableButtonRef = React.createRef();
92 const submitButtonRef = React.createRef();
@@ -125,7 +123,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
123 );
124 }
125
128 - const root = ReactDOM.unstable_createRoot(container);
126 + const root = ReactDOM.createRoot(container);
127 root.render(<Form />);
128 // Flush
129 Scheduler.unstable_flushAll();
@@ -157,7 +155,6 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
155 expect(formSubmitted).toBe(false);
156 });
157
160 - // @gate experimental
158 it('uses the newest discrete events on a pending changed event listener', async () => {
159 const enableButtonRef = React.createRef();
160 const submitButtonRef = React.createRef();
@@ -188,7 +185,7 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
185 );
186 }
187
191 - const root = ReactDOM.unstable_createRoot(container);
188 + const root = ReactDOM.createRoot(container);
189 root.render(<Form />);
190 // Flush
191 Scheduler.unstable_flushAll();
@@ -220,9 +217,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
217 expect(formSubmitted).toBe(true);
218 });
219
223 - // @gate experimental
220 it('mouse over should be user-blocking but not discrete', async () => {
225 - const root = ReactDOM.unstable_createRoot(container);
221 + const root = ReactDOM.createRoot(container);
222
223 const target = React.createRef(null);
224 function Foo() {
@@ -251,9 +247,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
247 expect(container.textContent).toEqual('hovered');
248 });
249
254 - // @gate experimental
250 it('mouse enter should be user-blocking but not discrete', async () => {
256 - const root = ReactDOM.unstable_createRoot(container);
251 + const root = ReactDOM.createRoot(container);
252
253 const target = React.createRef(null);
254 function Foo() {
@@ -284,9 +279,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
279 expect(container.textContent).toEqual('hovered');
280 });
281
287 - // @gate experimental
282 it('continuous native events flush as expected', async () => {
289 - const root = ReactDOM.unstable_createRoot(container);
283 + const root = ReactDOM.createRoot(container);
284
285 const target = React.createRef(null);
286 function Foo({hovered}) {
@@ -324,9 +318,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
318 expect(container.textContent).toEqual('hovered');
319 });
320
327 - // @gate experimental
321 it('should batch inside native events', async () => {
329 - const root = ReactDOM.unstable_createRoot(container);
322 + const root = ReactDOM.createRoot(container);
323
324 const target = React.createRef(null);
325 function Foo() {
@@ -375,9 +368,8 @@ describe('ReactDOMNativeEventHeuristic-test', () => {
368 }
369 });
370
378 - // @gate experimental
371 it('should not flush discrete events at the end of outermost batchedUpdates', async () => {
380 - const root = ReactDOM.unstable_createRoot(container);
372 + const root = ReactDOM.createRoot(container);
373
374 let target;
375 function Foo() {
packages/react-dom/src/__tests__/ReactDOMNestedEvents-test.js
+1 -2
@@ -27,7 +27,6 @@ describe('ReactDOMNestedEvents', () => {
27 useState = React.useState;
28 });
29
30 - // @gate experimental
30 test('nested event dispatches should not cause updates to flush', async () => {
31 const buttonRef = React.createRef(null);
32 function App() {
@@ -58,7 +57,7 @@ describe('ReactDOMNestedEvents', () => {
57
58 const container = document.createElement('div');
59 document.body.appendChild(container);
61 - const root = ReactDOM.unstable_createRoot(container);
60 + const root = ReactDOM.createRoot(container);
61
62 await act(async () => {
63 root.render(<App />);
packages/react-dom/src/__tests__/ReactDOMRoot-test.js
+20 -28
@@ -28,15 +28,8 @@ describe('ReactDOMRoot', () => {
28 act = require('react-dom/test-utils').unstable_concurrentAct;
29 });
30
31 - if (!__EXPERIMENTAL__) {
32 - it('createRoot is not exposed in stable build', () => {
33 - expect(ReactDOM.unstable_createRoot).toBe(undefined);
34 - });
35 - return;
36 - }
37 -
31 it('renders children', () => {
39 - const root = ReactDOM.unstable_createRoot(container);
32 + const root = ReactDOM.createRoot(container);
33 root.render(<div>Hi</div>);
34 Scheduler.unstable_flushAll();
35 expect(container.textContent).toEqual('Hi');
@@ -44,7 +37,7 @@ describe('ReactDOMRoot', () => {
37
38 it('warns if a callback parameter is provided to render', () => {
39 const callback = jest.fn();
47 - const root = ReactDOM.unstable_createRoot(container);
40 + const root = ReactDOM.createRoot(container);
41 expect(() =>
42 root.render(<div>Hi</div>, callback),
43 ).toErrorDev(
@@ -58,7 +51,7 @@ describe('ReactDOMRoot', () => {
51
52 it('warns if a callback parameter is provided to unmount', () => {
53 const callback = jest.fn();
61 - const root = ReactDOM.unstable_createRoot(container);
54 + const root = ReactDOM.createRoot(container);
55 root.render(<div>Hi</div>);
56 expect(() =>
57 root.unmount(callback),
@@ -72,7 +65,7 @@ describe('ReactDOMRoot', () => {
65 });
66
67 it('unmounts children', () => {
75 - const root = ReactDOM.unstable_createRoot(container);
68 + const root = ReactDOM.createRoot(container);
69 root.render(<div>Hi</div>);
70 Scheduler.unstable_flushAll();
71 expect(container.textContent).toEqual('Hi');
@@ -95,7 +88,7 @@ describe('ReactDOMRoot', () => {
88 // Does not hydrate by default
89 const container1 = document.createElement('div');
90 container1.innerHTML = markup;
98 - const root1 = ReactDOM.unstable_createRoot(container1);
91 + const root1 = ReactDOM.createRoot(container1);
92 root1.render(
93 <div>
94 <span />
@@ -106,7 +99,7 @@ describe('ReactDOMRoot', () => {
99 // Accepts `hydrate` option
100 const container2 = document.createElement('div');
101 container2.innerHTML = markup;
109 - const root2 = ReactDOM.unstable_createRoot(container2, {hydrate: true});
102 + const root2 = ReactDOM.createRoot(container2, {hydrate: true});
103 root2.render(
104 <div>
105 <span />
@@ -138,7 +131,7 @@ describe('ReactDOMRoot', () => {
131
132 it('clears existing children', async () => {
133 container.innerHTML = '<div>a</div><div>b</div>';
141 - const root = ReactDOM.unstable_createRoot(container);
134 + const root = ReactDOM.createRoot(container);
135 root.render(
136 <div>
137 <span>c</span>
@@ -159,12 +152,12 @@ describe('ReactDOMRoot', () => {
152
153 it('throws a good message on invalid containers', () => {
154 expect(() => {
162 - ReactDOM.unstable_createRoot(<div>Hi</div>);
155 + ReactDOM.createRoot(<div>Hi</div>);
156 }).toThrow('createRoot(...): Target container is not a DOM element.');
157 });
158
159 it('warns when rendering with legacy API into createRoot() container', () => {
167 - const root = ReactDOM.unstable_createRoot(container);
160 + const root = ReactDOM.createRoot(container);
161 root.render(<div>Hi</div>);
162 Scheduler.unstable_flushAll();
163 expect(container.textContent).toEqual('Hi');
@@ -187,7 +180,7 @@ describe('ReactDOMRoot', () => {
180 });
181
182 it('warns when hydrating with legacy API into createRoot() container', () => {
190 - const root = ReactDOM.unstable_createRoot(container);
183 + const root = ReactDOM.createRoot(container);
184 root.render(<div>Hi</div>);
185 Scheduler.unstable_flushAll();
186 expect(container.textContent).toEqual('Hi');
@@ -207,7 +200,7 @@ describe('ReactDOMRoot', () => {
200 });
201
202 it('warns when unmounting with legacy API (no previous content)', () => {
210 - const root = ReactDOM.unstable_createRoot(container);
203 + const root = ReactDOM.createRoot(container);
204 root.render(<div>Hi</div>);
205 Scheduler.unstable_flushAll();
206 expect(container.textContent).toEqual('Hi');
@@ -236,7 +229,7 @@ describe('ReactDOMRoot', () => {
229 // Currently createRoot().render() doesn't clear this.
230 container.appendChild(document.createElement('div'));
231 // The rest is the same as test above.
239 - const root = ReactDOM.unstable_createRoot(container);
232 + const root = ReactDOM.createRoot(container);
233 root.render(<div>Hi</div>);
234 Scheduler.unstable_flushAll();
235 expect(container.textContent).toEqual('Hi');
@@ -262,7 +255,7 @@ describe('ReactDOMRoot', () => {
255 it('warns when passing legacy container to createRoot()', () => {
256 ReactDOM.render(<div>Hi</div>, container);
257 expect(() => {
265 - ReactDOM.unstable_createRoot(container);
258 + ReactDOM.createRoot(container);
259 }).toErrorDev(
260 'You are calling ReactDOM.createRoot() on a container that was previously ' +
261 'passed to ReactDOM.render(). This is not supported.',
@@ -271,9 +264,9 @@ describe('ReactDOMRoot', () => {
264 });
265
266 it('warns when creating two roots managing the same container', () => {
274 - ReactDOM.unstable_createRoot(container);
267 + ReactDOM.createRoot(container);
268 expect(() => {
276 - ReactDOM.unstable_createRoot(container);
269 + ReactDOM.createRoot(container);
270 }).toErrorDev(
271 'You are calling ReactDOM.createRoot() on a container that ' +
272 'has already been passed to createRoot() before. Instead, call ' +
@@ -283,15 +276,15 @@ describe('ReactDOMRoot', () => {
276 });
277
278 it('does not warn when creating second root after first one is unmounted', () => {
286 - const root = ReactDOM.unstable_createRoot(container);
279 + const root = ReactDOM.createRoot(container);
280 root.unmount();
281 Scheduler.unstable_flushAll();
289 - ReactDOM.unstable_createRoot(container); // No warning
282 + ReactDOM.createRoot(container); // No warning
283 });
284
285 it('warns if creating a root on the document.body', async () => {
286 expect(() => {
294 - ReactDOM.unstable_createRoot(document.body);
287 + ReactDOM.createRoot(document.body);
288 }).toErrorDev(
289 'createRoot(): Creating roots directly with document.body is ' +
290 'discouraged, since its children are often manipulated by third-party ' +
@@ -303,7 +296,7 @@ describe('ReactDOMRoot', () => {
296 });
297
298 it('warns if updating a root that has had its contents removed', async () => {
306 - const root = ReactDOM.unstable_createRoot(container);
299 + const root = ReactDOM.createRoot(container);
300 root.render(<div>Hi</div>);
301 Scheduler.unstable_flushAll();
302 container.innerHTML = '';
@@ -319,9 +312,8 @@ describe('ReactDOMRoot', () => {
312 );
313 });
314
322 - // @gate experimental
315 it('opts-in to concurrent default updates', async () => {
324 - const root = ReactDOM.unstable_createRoot(container, {
316 + const root = ReactDOM.createRoot(container, {
317 unstable_concurrentUpdatesByDefault: true,
318 });
319
packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js
+15 -39
@@ -895,7 +895,6 @@ describe('ReactDOMServerHooks', () => {
895 });
896
897 describe('useOpaqueIdentifier', () => {
898 - // @gate experimental
898 it('generates unique ids for server string render', async () => {
899 function App(props) {
900 const idOne = useOpaqueIdentifier();
@@ -929,7 +928,6 @@ describe('ReactDOMServerHooks', () => {
928 ).not.toBeNull();
929 });
930
932 - // @gate experimental
931 it('generates unique ids for server stream render', async () => {
932 function App(props) {
933 const idOne = useOpaqueIdentifier();
@@ -963,7 +961,6 @@ describe('ReactDOMServerHooks', () => {
961 ).not.toBeNull();
962 });
963
966 - // @gate experimental
964 it('generates unique ids for client render', async () => {
965 function App(props) {
966 const idOne = useOpaqueIdentifier();
@@ -997,7 +994,6 @@ describe('ReactDOMServerHooks', () => {
994 ).not.toBeNull();
995 });
996
1000 - // @gate experimental
997 it('generates unique ids for client render on good server markup', async () => {
998 function App(props) {
999 const idOne = useOpaqueIdentifier();
@@ -1031,7 +1027,6 @@ describe('ReactDOMServerHooks', () => {
1027 ).not.toBeNull();
1028 });
1029
1034 - // @gate experimental
1030 it('useOpaqueIdentifier does not change id even if the component updates during client render', async () => {
1031 let _setShowId;
1032 function App() {
@@ -1063,7 +1058,6 @@ describe('ReactDOMServerHooks', () => {
1058 );
1059 });
1060
1066 - // @gate experimental
1061 it('useOpaqueIdentifier identifierPrefix works for server renderer and does not clash', async () => {
1062 function ChildTwo({id}) {
1063 return <div id={id}>Child Three</div>;
@@ -1149,7 +1143,6 @@ describe('ReactDOMServerHooks', () => {
1143 ).toBe(true);
1144 });
1145
1152 - // @gate experimental
1146 it('useOpaqueIdentifier identifierPrefix works for multiple reads on a streaming server renderer', async () => {
1147 function ChildTwo() {
1148 const id = useOpaqueIdentifier();
@@ -1241,7 +1234,6 @@ describe('ReactDOMServerHooks', () => {
1234 await Promise.all([streamOneIsDone, streamTwoIsDone]);
1235 });
1236
1244 - // @gate experimental
1237 it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered', async () => {
1238 let _setShowDiv;
1239 function App() {
@@ -1261,7 +1253,7 @@ describe('ReactDOMServerHooks', () => {
1253 document.body.append(container);
1254
1255 container.innerHTML = ReactDOMServer.renderToString(<App />);
1264 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
1256 + const root = ReactDOM.createRoot(container, {hydrate: true});
1257 root.render(<App />);
1258 Scheduler.unstable_flushAll();
1259 jest.runAllTimers();
@@ -1285,7 +1277,6 @@ describe('ReactDOMServerHooks', () => {
1277 ).not.toBeNull();
1278 });
1279
1288 - // @gate experimental
1280 it('useOpaqueIdentifier: IDs match when, after hydration, a new component that uses the ID is rendered for legacy', async () => {
1281 let _setShowDiv;
1282 function App() {
@@ -1326,7 +1317,6 @@ describe('ReactDOMServerHooks', () => {
1317 ).not.toBeNull();
1318 });
1319
1329 - // @gate experimental
1320 it('useOpaqueIdentifier: ID is not used during hydration but is used in an update', async () => {
1321 let _setShow;
1322 function App({unused}) {
@@ -1344,7 +1334,7 @@ describe('ReactDOMServerHooks', () => {
1334 const container = document.createElement('div');
1335 document.body.append(container);
1336 container.innerHTML = ReactDOMServer.renderToString(<App />);
1347 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
1337 + const root = ReactDOM.createRoot(container, {hydrate: true});
1338 act(() => {
1339 root.render(<App />);
1340 });
@@ -1359,7 +1349,6 @@ describe('ReactDOMServerHooks', () => {
1349 ).not.toBeNull();
1350 });
1351
1362 - // @gate experimental
1352 it('useOpaqueIdentifier: ID is not used during hydration but is used in an update in legacy', async () => {
1353 let _setShow;
1354 function App({unused}) {
@@ -1389,7 +1378,6 @@ describe('ReactDOMServerHooks', () => {
1378 ).not.toBeNull();
1379 });
1380
1392 - // @gate experimental
1381 it('useOpaqueIdentifier: flushSync', async () => {
1382 let _setShow;
1383 function App() {
@@ -1406,7 +1394,7 @@ describe('ReactDOMServerHooks', () => {
1394 const container = document.createElement('div');
1395 document.body.append(container);
1396 container.innerHTML = ReactDOMServer.renderToString(<App />);
1409 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
1397 + const root = ReactDOM.createRoot(container, {hydrate: true});
1398 act(() => {
1399 root.render(<App />);
1400 });
@@ -1422,7 +1410,6 @@ describe('ReactDOMServerHooks', () => {
1410 ).not.toBeNull();
1411 });
1412
1425 - // @gate experimental
1413 it('useOpaqueIdentifier: children with id hydrates before other children if ID updates', async () => {
1414 let _setShow;
1415
@@ -1498,7 +1485,7 @@ describe('ReactDOMServerHooks', () => {
1485 .getAttribute('id');
1486 expect(serverId).not.toBeNull();
1487
1501 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
1488 + const root = ReactDOM.createRoot(container, {hydrate: true});
1489 root.render(<App show={false} />);
1490 expect(Scheduler).toHaveYielded([]);
1491
@@ -1546,7 +1533,6 @@ describe('ReactDOMServerHooks', () => {
1533 expect(Scheduler).toHaveYielded([]);
1534 });
1535
1549 - // @gate experimental
1536 it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => {
1537 let suspend = true;
1538 let resolve;
@@ -1591,7 +1577,7 @@ describe('ReactDOMServerHooks', () => {
1577 container.innerHTML = ReactDOMServer.renderToString(<App />);
1578
1579 suspend = true;
1594 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
1580 + const root = ReactDOM.createRoot(container, {hydrate: true});
1581 await act(async () => {
1582 root.render(<App />);
1583 });
@@ -1627,7 +1613,6 @@ describe('ReactDOMServerHooks', () => {
1613 ).not.toBeNull();
1614 });
1615
1630 - // @gate experimental
1616 it('useOpaqueIdentifier warn when there is a hydration error', async () => {
1617 function Child({appId}) {
1618 return <div aria-labelledby={appId} />;
@@ -1642,7 +1627,7 @@ describe('ReactDOMServerHooks', () => {
1627
1628 // This is the wrong HTML string
1629 container.innerHTML = '<span></span>';
1645 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1630 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1631 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1632 [
1633 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
@@ -1652,7 +1637,6 @@ describe('ReactDOMServerHooks', () => {
1637 );
1638 });
1639
1655 - // @gate experimental
1640 it('useOpaqueIdentifier: IDs match when part of the DOM tree is server rendered and part is client rendered', async () => {
1641 let suspend = true;
1642
@@ -1695,7 +1679,7 @@ describe('ReactDOMServerHooks', () => {
1679 container.innerHTML = ReactDOMServer.renderToString(<App />);
1680
1681 suspend = false;
1698 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
1682 + const root = ReactDOM.createRoot(container, {hydrate: true});
1683 await act(async () => {
1684 root.render(<App />);
1685 });
@@ -1717,7 +1701,6 @@ describe('ReactDOMServerHooks', () => {
1701 ).not.toBeNull();
1702 });
1703
1720 - // @gate experimental
1704 it('useOpaqueIdentifier warn when there is a hydration error', async () => {
1705 function Child({appId}) {
1706 return <div aria-labelledby={appId} />;
@@ -1732,7 +1715,7 @@ describe('ReactDOMServerHooks', () => {
1715
1716 // This is the wrong HTML string
1717 container.innerHTML = '<span></span>';
1735 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1718 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1719 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1720 [
1721 'Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.',
@@ -1742,7 +1725,6 @@ describe('ReactDOMServerHooks', () => {
1725 );
1726 });
1727
1745 - // @gate experimental
1728 it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => {
1729 function Child({appId}) {
1730 return <div aria-labelledby={appId + ''} />;
@@ -1757,7 +1739,7 @@ describe('ReactDOMServerHooks', () => {
1739
1740 // This is the wrong HTML string
1741 container.innerHTML = '<span></span>';
1760 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1742 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1743 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1744 [
1745 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@@ -1767,7 +1749,6 @@ describe('ReactDOMServerHooks', () => {
1749 );
1750 });
1751
1770 - // @gate experimental
1752 it('useOpaqueIdentifier warns when there is a hydration error and we are using ID as a string', async () => {
1753 function Child({appId}) {
1754 return <div aria-labelledby={appId + ''} />;
@@ -1782,7 +1763,7 @@ describe('ReactDOMServerHooks', () => {
1763
1764 // This is the wrong HTML string
1765 container.innerHTML = '<span></span>';
1785 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1766 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1767 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1768 [
1769 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@@ -1792,7 +1773,6 @@ describe('ReactDOMServerHooks', () => {
1773 );
1774 });
1775
1795 - // @gate experimental
1776 it('useOpaqueIdentifier warns if you try to use the result as a string in a child component', async () => {
1777 function Child({appId}) {
1778 return <div aria-labelledby={appId + ''} />;
@@ -1806,7 +1786,7 @@ describe('ReactDOMServerHooks', () => {
1786 document.body.appendChild(container);
1787
1788 container.innerHTML = ReactDOMServer.renderToString(<App />);
1809 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1789 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1790 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1791 [
1792 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@@ -1816,7 +1796,6 @@ describe('ReactDOMServerHooks', () => {
1796 );
1797 });
1798
1819 - // @gate experimental
1799 it('useOpaqueIdentifier warns if you try to use the result as a string', async () => {
1800 function App() {
1801 const id = useOpaqueIdentifier();
@@ -1827,7 +1806,7 @@ describe('ReactDOMServerHooks', () => {
1806 document.body.appendChild(container);
1807
1808 container.innerHTML = ReactDOMServer.renderToString(<App />);
1830 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1809 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1810 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
1811 [
1812 'Warning: The object passed back from useOpaqueIdentifier is meant to be passed through to attributes only. Do not read the value directly.',
@@ -1837,7 +1816,6 @@ describe('ReactDOMServerHooks', () => {
1816 );
1817 });
1818
1840 - // @gate experimental
1819 it('useOpaqueIdentifier warns if you try to use the result as a string in a child component wrapped in a Suspense', async () => {
1820 function Child({appId}) {
1821 return <div aria-labelledby={appId + ''} />;
@@ -1856,7 +1834,7 @@ describe('ReactDOMServerHooks', () => {
1834
1835 container.innerHTML = ReactDOMServer.renderToString(<App />);
1836
1859 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1837 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1838
1839 if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) {
1840 expect(() => Scheduler.unstable_flushAll()).toErrorDev([
@@ -1878,7 +1856,6 @@ describe('ReactDOMServerHooks', () => {
1856 }
1857 });
1858
1881 - // @gate experimental
1859 it('useOpaqueIdentifier warns if you try to add the result as a number in a child component wrapped in a Suspense', async () => {
1860 function Child({appId}) {
1861 return <div aria-labelledby={+appId} />;
@@ -1899,7 +1876,7 @@ describe('ReactDOMServerHooks', () => {
1876
1877 container.innerHTML = ReactDOMServer.renderToString(<App />);
1878
1902 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1879 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1880
1881 if (gate(flags => flags.deferRenderPhaseUpdateToNextBatch)) {
1882 expect(() => Scheduler.unstable_flushAll()).toErrorDev([
@@ -1921,7 +1898,6 @@ describe('ReactDOMServerHooks', () => {
1898 }
1899 });
1900
1924 - // @gate experimental
1901 it('useOpaqueIdentifier with two opaque identifiers on the same page', () => {
1902 let _setShow;
1903
@@ -1960,7 +1936,7 @@ describe('ReactDOMServerHooks', () => {
1936 .getAttribute('aria-labelledby'),
1937 ).toEqual(serverID);
1938
1963 - ReactDOM.unstable_createRoot(container, {hydrate: true}).render(<App />);
1939 + ReactDOM.createRoot(container, {hydrate: true}).render(<App />);
1940 jest.runAllTimers();
1941 expect(Scheduler).toHaveYielded([]);
1942 expect(Scheduler).toFlushAndYield([]);
packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js
+2 -35
@@ -102,7 +102,6 @@ describe('ReactDOMServerPartialHydration', () => {
102 );
103 }
104
105 - // @gate experimental
105 it('hydrates a parent even if a child Suspense boundary is blocked', async () => {
106 let suspend = false;
107 let resolve;
@@ -161,7 +160,6 @@ describe('ReactDOMServerPartialHydration', () => {
160 expect(ref.current).toBe(span);
161 });
162
164 - // @gate experimental
163 it('calls the hydration callbacks after hydration or deletion', async () => {
164 let suspend = false;
165 let resolve;
@@ -252,7 +250,6 @@ describe('ReactDOMServerPartialHydration', () => {
250 expect(deleted.length).toBe(1);
251 });
252
255 - // @gate experimental
253 it('calls the onDeleted hydration callback if the parent gets deleted', async () => {
254 let suspend = false;
255 const promise = new Promise(() => {});
@@ -310,7 +307,6 @@ describe('ReactDOMServerPartialHydration', () => {
307 expect(deleted.length).toBe(1);
308 });
309
313 - // @gate experimental || www
310 it('warns and replaces the boundary content in legacy mode', async () => {
311 let suspend = false;
312 let resolve;
@@ -390,7 +386,6 @@ describe('ReactDOMServerPartialHydration', () => {
386 expect(container.textContent).toBe('Hello');
387 });
388
393 - // @gate experimental
389 it('can insert siblings before the dehydrated boundary', () => {
390 let suspend = false;
391 const promise = new Promise(() => {});
@@ -449,7 +444,6 @@ describe('ReactDOMServerPartialHydration', () => {
444 expect(container.firstChild.firstChild.textContent).toBe('First');
445 });
446
452 - // @gate experimental
447 it('can delete the dehydrated boundary before it is hydrated', () => {
448 let suspend = false;
449 const promise = new Promise(() => {});
@@ -506,7 +500,6 @@ describe('ReactDOMServerPartialHydration', () => {
500 expect(container.firstChild.children[1].textContent).toBe('After');
501 });
502
509 - // @gate experimental
503 it('blocks updates to hydrate the content first if props have changed', async () => {
504 let suspend = false;
505 let resolve;
@@ -652,7 +645,6 @@ describe('ReactDOMServerPartialHydration', () => {
645 expect(span.className).toBe('hi');
646 });
647
655 - // @gate experimental
648 it('shows the fallback if props have changed before hydration completes and is still suspended', async () => {
649 let suspend = false;
650 let resolve;
@@ -722,7 +714,6 @@ describe('ReactDOMServerPartialHydration', () => {
714 expect(container.textContent).toBe('Hi');
715 });
716
725 - // @gate experimental
717 it('shows the fallback of the outer if fallback is missing', async () => {
718 // This is the same exact test as above but with a nested Suspense without a fallback.
719 // This should be a noop.
@@ -796,7 +787,6 @@ describe('ReactDOMServerPartialHydration', () => {
787 expect(container.textContent).toBe('Hi');
788 });
789
799 - // @gate experimental
790 it('clears nested suspense boundaries if they did not hydrate yet', async () => {
791 let suspend = false;
792 let resolve;
@@ -869,7 +859,6 @@ describe('ReactDOMServerPartialHydration', () => {
859 expect(container.textContent).toBe('Hi Hi');
860 });
861
872 - // @gate experimental
862 it('hydrates first if props changed but we are able to resolve within a timeout', async () => {
863 let suspend = false;
864 let resolve;
@@ -917,9 +906,7 @@ describe('ReactDOMServerPartialHydration', () => {
906 expect(container.textContent).toBe('Hello');
907
908 // Render an update with a long timeout.
920 - React.unstable_startTransition(() =>
921 - root.render(<App text="Hi" className="hi" />),
922 - );
909 + React.startTransition(() => root.render(<App text="Hi" className="hi" />));
910
911 // This shouldn't force the fallback yet.
912 Scheduler.unstable_flushAll();
@@ -949,7 +936,6 @@ describe('ReactDOMServerPartialHydration', () => {
936 expect(span.className).toBe('hi');
937 });
938
952 - // @gate experimental
939 it('warns but works if setState is called before commit in a dehydrated component', async () => {
940 let suspend = false;
941 let resolve;
@@ -1018,7 +1004,6 @@ describe('ReactDOMServerPartialHydration', () => {
1004 expect(container.textContent).toBe('Hello');
1005 });
1006
1021 - // @gate experimental
1007 it('blocks the update to hydrate first if context has changed', async () => {
1008 let suspend = false;
1009 let resolve;
@@ -1103,7 +1088,6 @@ describe('ReactDOMServerPartialHydration', () => {
1088 expect(span.className).toBe('hi');
1089 });
1090
1106 - // @gate experimental
1091 it('shows the fallback if context has changed before hydration completes and is still suspended', async () => {
1092 let suspend = false;
1093 let resolve;
@@ -1187,7 +1171,6 @@ describe('ReactDOMServerPartialHydration', () => {
1171 expect(container.textContent).toBe('Hi');
1172 });
1173
1190 - // @gate experimental
1174 it('replaces the fallback with client content if it is not rendered by the server', async () => {
1175 let suspend = false;
1176 const promise = new Promise(resolvePromise => {});
@@ -1236,7 +1219,6 @@ describe('ReactDOMServerPartialHydration', () => {
1219 expect(ref.current).toBe(span);
1220 });
1221
1239 - // @gate experimental
1222 it('replaces the fallback within the suspended time if there is a nested suspense', async () => {
1223 let suspend = false;
1224 const promise = new Promise(resolvePromise => {});
@@ -1296,7 +1278,6 @@ describe('ReactDOMServerPartialHydration', () => {
1278 expect(ref.current).toBe(span);
1279 });
1280
1299 - // @gate experimental
1281 it('replaces the fallback within the suspended time if there is a nested suspense in a nested suspense', async () => {
1282 let suspend = false;
1283 const promise = new Promise(resolvePromise => {});
@@ -1358,7 +1339,6 @@ describe('ReactDOMServerPartialHydration', () => {
1339 expect(ref.current).toBe(span);
1340 });
1341
1361 - // @gate experimental
1342 it('shows inserted items in a SuspenseList before content is hydrated', async () => {
1343 let suspend = false;
1344 let resolve;
@@ -1444,7 +1424,6 @@ describe('ReactDOMServerPartialHydration', () => {
1424 expect(ref.current).toBe(spanB);
1425 });
1426
1447 - // @gate experimental
1427 it('shows is able to hydrate boundaries even if others in a list are pending', async () => {
1428 let suspend = false;
1429 let resolve;
@@ -1591,7 +1570,7 @@ describe('ReactDOMServerPartialHydration', () => {
1570
1571 await act(async () => {
1572 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1594 - React.unstable_startTransition(() => {
1573 + React.startTransition(() => {
1574 root.render(<App />);
1575 });
1576
@@ -1622,7 +1601,6 @@ describe('ReactDOMServerPartialHydration', () => {
1601 expect(ref.current).toBe(b);
1602 });
1603
1625 - // @gate experimental
1604 it('clears server boundaries when SuspenseList suspends last row hydrating', async () => {
1605 let suspend = false;
1606 let resolve;
@@ -1679,7 +1657,6 @@ describe('ReactDOMServerPartialHydration', () => {
1657 expect(container.textContent).toBe('AB');
1658 });
1659
1682 - // @gate experimental
1660 it('can client render nested boundaries', async () => {
1661 let suspend = false;
1662 const promise = new Promise(() => {});
@@ -1734,7 +1711,6 @@ describe('ReactDOMServerPartialHydration', () => {
1711 expect(container.lastChild.data).toBe('unrelated comment');
1712 });
1713
1737 - // @gate experimental
1714 it('can hydrate TWO suspense boundaries', async () => {
1715 const ref1 = React.createRef();
1716 const ref2 = React.createRef();
@@ -1774,7 +1750,6 @@ describe('ReactDOMServerPartialHydration', () => {
1750 expect(ref2.current).toBe(span2);
1751 });
1752
1777 - // @gate experimental
1753 it('regenerates if it cannot hydrate before changes to props/context expire', async () => {
1754 let suspend = false;
1755 const promise = new Promise(resolvePromise => {});
@@ -1856,7 +1831,6 @@ describe('ReactDOMServerPartialHydration', () => {
1831 expect(newSpan.className).toBe('hi');
1832 });
1833
1859 - // @gate experimental
1834 it('does not invoke an event on a hydrated node until it commits', async () => {
1835 let suspend = false;
1836 let resolve;
@@ -2022,7 +1996,6 @@ describe('ReactDOMServerPartialHydration', () => {
1996 document.body.removeChild(container);
1997 });
1998
2025 - // @gate experimental
1999 it('invokes discrete events on nested suspense boundaries in a root (legacy system)', async () => {
2000 let suspend = false;
2001 let resolve;
@@ -2190,7 +2163,6 @@ describe('ReactDOMServerPartialHydration', () => {
2163 document.body.removeChild(container);
2164 });
2165
2193 - // @gate experimental
2166 it('does not invoke the parent of dehydrated boundary event', async () => {
2167 let suspend = false;
2168 let resolve;
@@ -2266,7 +2238,6 @@ describe('ReactDOMServerPartialHydration', () => {
2238 document.body.removeChild(container);
2239 });
2240
2269 - // @gate experimental
2241 it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => {
2242 let suspend = false;
2243 let resolve;
@@ -2345,7 +2316,6 @@ describe('ReactDOMServerPartialHydration', () => {
2316 document.body.removeChild(parentContainer);
2317 });
2318
2348 - // @gate experimental
2319 it('blocks only on the last continuous event (legacy system)', async () => {
2320 let suspend1 = false;
2321 let resolve1;
@@ -2450,7 +2420,6 @@ describe('ReactDOMServerPartialHydration', () => {
2420 document.body.removeChild(container);
2421 });
2422
2453 - // @gate experimental
2423 it('finishes normal pri work before continuing to hydrate a retry', async () => {
2424 let suspend = false;
2425 let resolve;
@@ -2532,7 +2501,6 @@ describe('ReactDOMServerPartialHydration', () => {
2501 expect(ref.current).not.toBe(null);
2502 });
2503
2535 - // @gate experimental
2504 it('regression test: does not overfire non-bubbling browser events', async () => {
2505 let suspend = false;
2506 let resolve;
@@ -2623,7 +2591,6 @@ describe('ReactDOMServerPartialHydration', () => {
2591 // follow up.
2592 //
2593 // @gate FIXME
2626 - // @gate experimental
2594 it('hydrates a hidden subtree outside of a Suspense boundary', async () => {
2595 const ref = React.createRef();
2596
packages/react-dom/src/__tests__/ReactDOMServerSelectiveHydration-test.internal.js
-5
@@ -126,7 +126,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
126 IdleEventPriority = require('react-reconciler/constants').IdleEventPriority;
127 });
128
129 - // @gate experimental
129 it('hydrates the target boundary synchronously during a click', async () => {
130 function Child({text}) {
131 Scheduler.unstable_yieldValue(text);
@@ -189,7 +188,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
188 document.body.removeChild(container);
189 });
190
192 - // @gate experimental
191 it('hydrates at higher pri if sync did not work first time', async () => {
192 let suspend = false;
193 let resolve;
@@ -277,7 +275,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
275 document.body.removeChild(container);
276 });
277
280 - // @gate experimental
278 it('hydrates at higher pri for secondary discrete events', async () => {
279 let suspend = false;
280 let resolve;
@@ -628,7 +625,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
625 document.body.removeChild(container);
626 });
627
631 - // @gate experimental
628 it('hydrates the hovered targets as higher priority for continuous events', async () => {
629 let suspend = false;
630 let resolve;
@@ -731,7 +727,6 @@ describe('ReactDOMServerSelectiveHydration', () => {
727 document.body.removeChild(container);
728 });
729
734 - // @gate experimental
730 it('hydrates the last target path first for continuous events', async () => {
731 let suspend = false;
732 let resolve;
packages/react-dom/src/__tests__/ReactDOMServerSuspense-test.internal.js
-4
@@ -93,7 +93,6 @@ describe('ReactDOMServerSuspense', () => {
93 : children;
94 }
95
96 - // @gate experimental || www
96 it('should render the children when no promise is thrown', async () => {
97 const c = await serverRender(
98 <div>
@@ -105,7 +104,6 @@ describe('ReactDOMServerSuspense', () => {
104 expect(getVisibleChildren(c)).toEqual(<div>Children</div>);
105 });
106
108 - // @gate experimental || www
107 it('should render the fallback when a promise thrown', async () => {
108 const c = await serverRender(
109 <div>
@@ -117,7 +115,6 @@ describe('ReactDOMServerSuspense', () => {
115 expect(getVisibleChildren(c)).toEqual(<div>Fallback</div>);
116 });
117
120 - // @gate experimental || www
118 it('should work with nested suspense components', async () => {
119 const c = await serverRender(
120 <div>
@@ -140,7 +137,6 @@ describe('ReactDOMServerSuspense', () => {
137 );
138 });
139
143 - // @gate experimental
140 it('server renders a SuspenseList component and its children', async () => {
141 const example = (
142 <React.SuspenseList>
packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js
+1 -2
@@ -492,12 +492,11 @@ describe('ReactDOMServerHydration', () => {
492 expect(element.textContent).toBe('Hello world');
493 });
494
495 - // @gate experimental
495 it('does not re-enter hydration after committing the first one', () => {
496 const finalHTML = ReactDOMServer.renderToString(<div />);
497 const container = document.createElement('div');
498 container.innerHTML = finalHTML;
500 - const root = ReactDOM.unstable_createRoot(container, {hydrate: true});
499 + const root = ReactDOM.createRoot(container, {hydrate: true});
500 root.render(<div />);
501 Scheduler.unstable_flushAll();
502 root.render(null);
packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
+6 -9
@@ -29,7 +29,7 @@ describe('ReactTestUtils.act()', () => {
29 if (__EXPERIMENTAL__) {
30 let concurrentRoot = null;
31 const renderConcurrent = (el, dom) => {
32 - concurrentRoot = ReactDOM.unstable_createRoot(dom);
32 + concurrentRoot = ReactDOM.createRoot(dom);
33 concurrentRoot.render(el);
34 };
35
@@ -96,20 +96,17 @@ describe('ReactTestUtils.act()', () => {
96 ]);
97 });
98
99 - // @gate experimental
99 it('does not warn in concurrent mode', () => {
101 - const root = ReactDOM.unstable_createRoot(document.createElement('div'));
100 + const root = ReactDOM.createRoot(document.createElement('div'));
101 root.render(<App />);
102 Scheduler.unstable_flushAll();
103 });
104
106 - // @gate experimental
105 it('warns in concurrent mode if root is strict', () => {
106 expect(() => {
109 - const root = ReactDOM.unstable_createRoot(
110 - document.createElement('div'),
111 - {unstable_strictMode: true},
112 - );
107 + const root = ReactDOM.createRoot(document.createElement('div'), {
108 + unstable_strictMode: true,
109 + });
110 root.render(<App />);
111 Scheduler.unstable_flushAll();
112 }).toErrorDev([
@@ -665,7 +662,7 @@ function runActTests(label, render, unmount, rerender) {
662 expect(document.querySelector('[data-test-id=spinner]')).toBeNull();
663
664 // trigger a suspendy update with a delay
668 - React.unstable_startTransition(() => {
665 + React.startTransition(() => {
666 act(() => {
667 rerender(<App suspend={true} />);
668 });
packages/react-dom/src/__tests__/ReactUnmockedSchedulerWarning-test.js
+2 -3
@@ -29,10 +29,9 @@ it('does not warn when rendering in legacy mode', () => {
29 }).toErrorDev([]);
30 });
31
32 -// @gate experimental
32 it('should warn when rendering in concurrent mode', () => {
33 expect(() => {
35 - ReactDOM.unstable_createRoot(document.createElement('div')).render(<App />);
34 + ReactDOM.createRoot(document.createElement('div')).render(<App />);
35 }).toErrorDev(
36 'In Concurrent or Sync modes, the "scheduler" module needs to be mocked ' +
37 'to guarantee consistent behaviour across tests and browsers.',
@@ -40,6 +39,6 @@ it('should warn when rendering in concurrent mode', () => {
39 );
40 // does not warn twice
41 expect(() => {
43 - ReactDOM.unstable_createRoot(document.createElement('div')).render(<App />);
42 + ReactDOM.createRoot(document.createElement('div')).render(<App />);
43 }).toErrorDev([]);
44 });
packages/react-dom/src/__tests__/ReactUpdates-test.js
+1 -1
@@ -1332,7 +1332,7 @@ describe('ReactUpdates', () => {
1332 );
1333 }
1334
1335 - const root = ReactDOM.unstable_createRoot(container);
1335 + const root = ReactDOM.createRoot(container);
1336 let hiddenDiv;
1337 act(() => {
1338 root.render(<Foo />);
packages/react-dom/src/__tests__/ReactWrongReturnPointer-test.js
+1 -1
@@ -22,7 +22,7 @@ beforeEach(() => {
22 Scheduler = require('scheduler');
23
24 Suspense = React.Suspense;
25 - SuspenseList = React.unstable_SuspenseList;
25 + SuspenseList = React.SuspenseList;
26
27 getCacheForType = React.unstable_getCacheForType;
28
packages/react-dom/src/client/ReactDOM.js
-24
@@ -78,7 +78,6 @@ setAttemptHydrationAtCurrentPriority(attemptHydrationAtCurrentPriority);
78 setGetCurrentUpdatePriority(getCurrentUpdatePriority);
79 setAttemptHydrationAtPriority(runWithPriority);
80
81 -let didWarnAboutUnstableCreatePortal = false;
81 let didWarnAboutUnstableRenderSubtreeIntoContainer = false;
82
83 if (__DEV__) {
@@ -155,25 +154,6 @@ function renderSubtreeIntoContainer(
154 );
155 }
156
158 -function unstable_createPortal(
159 - children: ReactNodeList,
160 - container: Container,
161 - key: ?string = null,
162 -) {
163 - if (__DEV__) {
164 - if (!didWarnAboutUnstableCreatePortal) {
165 - didWarnAboutUnstableCreatePortal = true;
166 - console.warn(
167 - 'The ReactDOM.unstable_createPortal() alias has been deprecated, ' +
168 - 'and will be removed in React 18+. Update your code to use ' +
169 - 'ReactDOM.createPortal() instead. It has the exact same API, ' +
170 - 'but without the "unstable_" prefix.',
171 - );
172 - }
173 - }
174 - return createPortal(children, container, key);
175 -}
176 -
157 const Internals = {
158 // Keep in sync with ReactTestUtils.js, and ReactTestUtilsAct.js.
159 // This is an array for better minification.
@@ -206,10 +186,6 @@ export {
186 scheduleHydration as unstable_scheduleHydration,
187 // Disabled behind disableUnstableRenderSubtreeIntoContainer
188 renderSubtreeIntoContainer as unstable_renderSubtreeIntoContainer,
209 - // Disabled behind disableUnstableCreatePortal
210 - // Temporary alias since we already shipped React 16 RC with it.
211 - // TODO: remove in React 18.
212 - unstable_createPortal,
189 // enableCreateEventHandleAPI
190 createEventHandle as unstable_createEventHandle,
191 // TODO: Remove this once callers migrate to alternatives.
packages/react-dom/src/events/__tests__/DOMPluginEventSystem-test.internal.js
+1 -2
@@ -575,7 +575,6 @@ describe('DOMPluginEventSystem', () => {
575 expect(log).toEqual(['second', 'first']);
576 });
577
578 - // @gate experimental
578 it('does not invoke an event on a parent tree when a subtree is dehydrated', async () => {
579 let suspend = false;
580 let resolve;
@@ -1951,7 +1950,7 @@ describe('DOMPluginEventSystem', () => {
1950
1951 // Increase counter
1952 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1954 - React.unstable_startTransition(() => {
1953 + React.startTransition(() => {
1954 root.render(<Test counter={1} />);
1955 });
1956 } else {
packages/react-dom/src/events/plugins/__tests__/ChangeEventPlugin-test.js
+6 -12
@@ -495,9 +495,8 @@ describe('ChangeEventPlugin', () => {
495 });
496
497 describe('concurrent mode', () => {
498 - // @gate experimental
498 it('text input', () => {
500 - const root = ReactDOM.unstable_createRoot(container);
499 + const root = ReactDOM.createRoot(container);
500 let input;
501
502 class ControlledInput extends React.Component {
@@ -538,9 +537,8 @@ describe('ChangeEventPlugin', () => {
537 expect(input.value).toBe('changed [!]');
538 });
539
541 - // @gate experimental
540 it('checkbox input', () => {
543 - const root = ReactDOM.unstable_createRoot(container);
541 + const root = ReactDOM.createRoot(container);
542 let input;
543
544 class ControlledInput extends React.Component {
@@ -594,9 +592,8 @@ describe('ChangeEventPlugin', () => {
592 expect(input.checked).toBe(false);
593 });
594
597 - // @gate experimental
595 it('textarea', () => {
599 - const root = ReactDOM.unstable_createRoot(container);
596 + const root = ReactDOM.createRoot(container);
597 let textarea;
598
599 class ControlledTextarea extends React.Component {
@@ -637,9 +634,8 @@ describe('ChangeEventPlugin', () => {
634 expect(textarea.value).toBe('changed [!]');
635 });
636
640 - // @gate experimental
637 it('parent of input', () => {
642 - const root = ReactDOM.unstable_createRoot(container);
638 + const root = ReactDOM.createRoot(container);
639 let input;
640
641 class ControlledInput extends React.Component {
@@ -684,9 +680,8 @@ describe('ChangeEventPlugin', () => {
680 expect(input.value).toBe('changed [!]');
681 });
682
687 - // @gate experimental
683 it('is sync for non-input events', async () => {
689 - const root = ReactDOM.unstable_createRoot(container);
684 + const root = ReactDOM.createRoot(container);
685 let input;
686
687 class ControlledInput extends React.Component {
@@ -731,12 +726,11 @@ describe('ChangeEventPlugin', () => {
726 expect(input.value).toBe('');
727 });
728
734 - // @gate experimental
729 it('mouse enter/leave should be user-blocking but not discrete', async () => {
730 const {unstable_concurrentAct: act} = TestUtils;
731 const {useState} = React;
732
739 - const root = ReactDOM.unstable_createRoot(container);
733 + const root = ReactDOM.createRoot(container);
734
735 const target = React.createRef(null);
736 function Foo() {
packages/react-dom/src/events/plugins/__tests__/SimpleEventPlugin-test.js
+2 -4
@@ -240,10 +240,9 @@ describe('SimpleEventPlugin', function() {
240 act = require('react-dom/test-utils').unstable_concurrentAct;
241 });
242
243 - // @gate experimental
243 it('flushes pending interactive work before exiting event handler', async () => {
244 container = document.createElement('div');
246 - const root = ReactDOM.unstable_createRoot(container);
245 + const root = ReactDOM.createRoot(container);
246 document.body.appendChild(container);
247
248 let button;
@@ -316,10 +315,9 @@ describe('SimpleEventPlugin', function() {
315 // NOTE: This test was written for the old behavior of discrete updates,
316 // where they would be async, but flushed early if another discrete update
317 // was dispatched.
319 - // @gate experimental
318 it('end result of many interactive updates is deterministic', async () => {
319 container = document.createElement('div');
322 - const root = ReactDOM.unstable_createRoot(container);
320 + const root = ReactDOM.createRoot(container);
321 document.body.appendChild(container);
322
323 let button;
packages/react-is/index.experimental.js
+2 -2
@@ -23,7 +23,7 @@ export {
23 Profiler,
24 StrictMode,
25 Suspense,
26 - unstable_SuspenseList,
26 + SuspenseList,
27 isAsyncMode,
28 isConcurrentMode,
29 isContextConsumer,
@@ -37,5 +37,5 @@ export {
37 isProfiler,
38 isStrictMode,
39 isSuspense,
40 - unstable_isSuspenseList,
40 + isSuspenseList,
41 } from './src/ReactIs';
packages/react-is/index.stable.js
+2
@@ -23,6 +23,7 @@ export {
23 Profiler,
24 StrictMode,
25 Suspense,
26 + SuspenseList,
27 isAsyncMode,
28 isConcurrentMode,
29 isContextConsumer,
@@ -36,4 +37,5 @@ export {
37 isProfiler,
38 isStrictMode,
39 isSuspense,
40 + isSuspenseList,
41 } from './src/ReactIs';
packages/react-is/src/ReactIs.js
+2 -2
@@ -72,7 +72,7 @@ export const Portal = REACT_PORTAL_TYPE;
72 export const Profiler = REACT_PROFILER_TYPE;
73 export const StrictMode = REACT_STRICT_MODE_TYPE;
74 export const Suspense = REACT_SUSPENSE_TYPE;
75 -export const unstable_SuspenseList = REACT_SUSPENSE_LIST_TYPE;
75 +export const SuspenseList = REACT_SUSPENSE_LIST_TYPE;
76
77 export {isValidElementType};
78
@@ -143,6 +143,6 @@ export function isStrictMode(object: any) {
143 export function isSuspense(object: any) {
144 return typeOf(object) === REACT_SUSPENSE_TYPE;
145 }
146 -export function unstable_isSuspenseList(object: any) {
146 +export function isSuspenseList(object: any) {
147 return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
148 }
packages/react-is/src/__tests__/ReactIs-test.js
+6 -15
@@ -186,22 +186,13 @@ describe('ReactIs', () => {
186 expect(ReactIs.isSuspense(<div />)).toBe(false);
187 });
188
189 - // @gate experimental
189 it('should identify suspense list', () => {
191 - expect(ReactIs.isValidElementType(React.unstable_SuspenseList)).toBe(true);
192 - expect(ReactIs.typeOf(<React.unstable_SuspenseList />)).toBe(
193 - ReactIs.unstable_SuspenseList,
194 - );
195 - expect(
196 - ReactIs.unstable_isSuspenseList(<React.unstable_SuspenseList />),
197 - ).toBe(true);
198 - expect(
199 - ReactIs.unstable_isSuspenseList({type: ReactIs.unstable_SuspenseList}),
200 - ).toBe(false);
201 - expect(ReactIs.unstable_isSuspenseList('React.unstable_SuspenseList')).toBe(
202 - false,
203 - );
204 - expect(ReactIs.unstable_isSuspenseList(<div />)).toBe(false);
190 + expect(ReactIs.isValidElementType(React.SuspenseList)).toBe(true);
191 + expect(ReactIs.typeOf(<React.SuspenseList />)).toBe(ReactIs.SuspenseList);
192 + expect(ReactIs.isSuspenseList(<React.SuspenseList />)).toBe(true);
193 + expect(ReactIs.isSuspenseList({type: ReactIs.SuspenseList})).toBe(false);
194 + expect(ReactIs.isSuspenseList('React.SuspenseList')).toBe(false);
195 + expect(ReactIs.isSuspenseList(<div />)).toBe(false);
196 });
197
198 it('should identify profile root', () => {
packages/react-reconciler/src/__tests__/ReactCache-test.js
+1 -1
@@ -22,7 +22,7 @@ describe('ReactCache', () => {
22 Suspense = React.Suspense;
23 getCacheForType = React.unstable_getCacheForType;
24 useCacheRefresh = React.unstable_useCacheRefresh;
25 - startTransition = React.unstable_startTransition;
25 + startTransition = React.startTransition;
26 useState = React.useState;
27
28 caches = [];
packages/react-reconciler/src/__tests__/ReactContextPropagation-test.js
+1 -3
@@ -19,7 +19,7 @@ describe('ReactLazyContextPropagation', () => {
19 useState = React.useState;
20 useContext = React.useContext;
21 Suspense = React.Suspense;
22 - SuspenseList = React.unstable_SuspenseList;
22 + SuspenseList = React.SuspenseList;
23
24 getCacheForType = React.unstable_getCacheForType;
25
@@ -649,8 +649,6 @@ describe('ReactLazyContextPropagation', () => {
649 expect(root).toMatchRenderedOutput('BBB');
650 });
651
652 - // @gate enableCache
653 - // @gate experimental
652 test('contexts are propagated through SuspenseList', async () => {
653 // This kinda tests an implementation detail. SuspenseList has an early
654 // bailout that doesn't use `bailoutOnAlreadyFinishedWork`. It probably
packages/react-reconciler/src/__tests__/ReactDisableSchedulerTimeoutBasedOnReactExpirationTime-test.internal.js
+1 -2
@@ -45,7 +45,6 @@ describe('ReactSuspenseList', () => {
45 return Component;
46 }
47
48 - // @gate experimental || !enableSyncDefaultUpdates
48 it('appends rendering tasks to the end of the priority queue', async () => {
49 const A = createAsyncText('A');
50 const B = createAsyncText('B');
@@ -65,7 +64,7 @@ describe('ReactSuspenseList', () => {
64 expect(Scheduler).toFlushAndYield([]);
65
66 if (gate(flags => flags.enableSyncDefaultUpdates)) {
68 - React.unstable_startTransition(() => {
67 + React.startTransition(() => {
68 root.render(<App show={true} />);
69 });
70 } else {
packages/react-reconciler/src/__tests__/ReactExpiration-test.js
+14 -26
@@ -25,7 +25,7 @@ describe('ReactExpiration', () => {
25 React = require('react');
26 ReactNoop = require('react-noop-renderer');
27 Scheduler = require('scheduler');
28 - startTransition = React.unstable_startTransition;
28 + startTransition = React.startTransition;
29 useState = React.useState;
30 useEffect = React.useEffect;
31
@@ -115,10 +115,10 @@ describe('ReactExpiration', () => {
115 // Flush the sync task.
116 ReactNoop.flushSync();
117 }
118 - // @gate experimental || !enableSyncDefaultUpdates
118 +
119 it('increases priority of updates as time progresses', () => {
120 if (gate(flags => flags.enableSyncDefaultUpdates)) {
121 - React.unstable_startTransition(() => {
121 + React.startTransition(() => {
122 ReactNoop.render(<span prop="done" />);
123 });
124 } else {
@@ -142,7 +142,6 @@ describe('ReactExpiration', () => {
142 expect(ReactNoop.getChildren()).toEqual([span('done')]);
143 });
144
145 - // @gate experimental || !enableSyncDefaultUpdates
145 it('two updates of like priority in the same event always flush within the same batch', () => {
146 class TextClass extends React.Component {
147 componentDidMount() {
@@ -166,7 +165,7 @@ describe('ReactExpiration', () => {
165 // First, show what happens for updates in two separate events.
166 // Schedule an update.
167 if (gate(flags => flags.enableSyncDefaultUpdates)) {
169 - React.unstable_startTransition(() => {
168 + React.startTransition(() => {
169 ReactNoop.render(<TextClass text="A" />);
170 });
171 } else {
@@ -201,7 +200,6 @@ describe('ReactExpiration', () => {
200 expect(Scheduler).toFlushAndYield(['B [render]', 'B [commit]']);
201 });
202
204 - // @gate experimental || !enableSyncDefaultUpdates
203 it(
204 'two updates of like priority in the same event always flush within the ' +
205 "same batch, even if there's a sync update in between",
@@ -228,7 +226,7 @@ describe('ReactExpiration', () => {
226 // First, show what happens for updates in two separate events.
227 // Schedule an update.
228 if (gate(flags => flags.enableSyncDefaultUpdates)) {
231 - React.unstable_startTransition(() => {
229 + React.startTransition(() => {
230 ReactNoop.render(<TextClass text="A" />);
231 });
232 } else {
@@ -269,7 +267,6 @@ describe('ReactExpiration', () => {
267 },
268 );
269
272 - // @gate experimental || !enableSyncDefaultUpdates
270 it('cannot update at the same expiration time that is already rendering', () => {
271 const store = {text: 'initial'};
272 const subscribers = [];
@@ -307,7 +304,7 @@ describe('ReactExpiration', () => {
304
305 // Initial mount
306 if (gate(flags => flags.enableSyncDefaultUpdates)) {
310 - React.unstable_startTransition(() => {
307 + React.startTransition(() => {
308 ReactNoop.render(<App />);
309 });
310 } else {
@@ -326,7 +323,7 @@ describe('ReactExpiration', () => {
323
324 // Partial update
325 if (gate(flags => flags.enableSyncDefaultUpdates)) {
329 - React.unstable_startTransition(() => {
326 + React.startTransition(() => {
327 subscribers.forEach(s => s.setState({text: '1'}));
328 });
329 } else {
@@ -347,7 +344,6 @@ describe('ReactExpiration', () => {
344 ]);
345 });
346
350 - // @gate experimental || !enableSyncDefaultUpdates
347 it('stops yielding if CPU-bound update takes too long to finish', () => {
348 const root = ReactNoop.createRoot();
349 function App() {
@@ -363,7 +359,7 @@ describe('ReactExpiration', () => {
359 }
360
361 if (gate(flags => flags.enableSyncDefaultUpdates)) {
366 - React.unstable_startTransition(() => {
362 + React.startTransition(() => {
363 root.render(<App />);
364 });
365 } else {
@@ -381,7 +377,6 @@ describe('ReactExpiration', () => {
377 expect(root).toMatchRenderedOutput('ABCDE');
378 });
379
384 - // @gate experimental || !enableSyncDefaultUpdates
380 it('root expiration is measured from the time of the first update', () => {
381 Scheduler.unstable_advanceTime(10000);
382
@@ -398,7 +393,7 @@ describe('ReactExpiration', () => {
393 );
394 }
395 if (gate(flags => flags.enableSyncDefaultUpdates)) {
401 - React.unstable_startTransition(() => {
396 + React.startTransition(() => {
397 root.render(<App />);
398 });
399 } else {
@@ -416,7 +411,6 @@ describe('ReactExpiration', () => {
411 expect(root).toMatchRenderedOutput('ABCDE');
412 });
413
419 - // @gate experimental || !enableSyncDefaultUpdates
414 it('should measure expiration times relative to module initialization', () => {
415 // Tests an implementation detail where expiration times are computed using
416 // bitwise operations.
@@ -433,7 +427,7 @@ describe('ReactExpiration', () => {
427 ReactNoop = require('react-noop-renderer');
428
429 if (gate(flags => flags.enableSyncDefaultUpdates)) {
436 - React.unstable_startTransition(() => {
430 + React.startTransition(() => {
431 ReactNoop.render('Hi');
432 });
433 } else {
@@ -453,7 +447,6 @@ describe('ReactExpiration', () => {
447 expect(ReactNoop).toMatchRenderedOutput('Hi');
448 });
449
456 - // @gate experimental || !enableSyncDefaultUpdates
450 it('should measure callback timeout relative to current time, not start-up time', () => {
451 // Corresponds to a bugfix: https://github.com/facebook/react/pull/15479
452 // The bug wasn't caught by other tests because we use virtual times that
@@ -463,7 +456,7 @@ describe('ReactExpiration', () => {
456 Scheduler.unstable_advanceTime(10000);
457
458 if (gate(flags => flags.enableSyncDefaultUpdates)) {
466 - React.unstable_startTransition(() => {
459 + React.startTransition(() => {
460 ReactNoop.render('Hi');
461 });
462 } else {
@@ -481,7 +474,6 @@ describe('ReactExpiration', () => {
474 expect(ReactNoop).toMatchRenderedOutput('Hi');
475 });
476
484 - // @gate experimental || !enableSyncDefaultUpdates
477 it('prevents starvation by sync updates by disabling time slicing if too much time has elapsed', async () => {
478 let updateSyncPri;
479 let updateNormalPri;
@@ -513,7 +505,7 @@ describe('ReactExpiration', () => {
505 // First demonstrate what happens when there's no starvation
506 await ReactNoop.act(async () => {
507 if (gate(flags => flags.enableSyncDefaultUpdates)) {
516 - React.unstable_startTransition(() => {
508 + React.startTransition(() => {
509 updateNormalPri();
510 });
511 } else {
@@ -537,7 +529,7 @@ describe('ReactExpiration', () => {
529 // Do the same thing, but starve the first update
530 await ReactNoop.act(async () => {
531 if (gate(flags => flags.enableSyncDefaultUpdates)) {
540 - React.unstable_startTransition(() => {
532 + React.startTransition(() => {
533 updateNormalPri();
534 });
535 } else {
@@ -628,7 +620,6 @@ describe('ReactExpiration', () => {
620 expect(root).toMatchRenderedOutput('Sync pri: 2, Idle pri: 2');
621 });
622
631 - // @gate experimental
623 it('when multiple lanes expire, we can finish the in-progress one without including the others', async () => {
624 let setA;
625 let setB;
@@ -677,7 +668,6 @@ describe('ReactExpiration', () => {
668 });
669 });
670
680 - // @gate experimental || !enableSyncDefaultUpdates
671 it('updates do not expire while they are IO-bound', async () => {
672 const {Suspense} = React;
673
@@ -701,7 +691,7 @@ describe('ReactExpiration', () => {
691
692 await ReactNoop.act(async () => {
693 if (gate(flags => flags.enableSyncDefaultUpdates)) {
704 - React.unstable_startTransition(() => {
694 + React.startTransition(() => {
695 root.render(<App step={1} />);
696 });
697 } else {
@@ -734,7 +724,6 @@ describe('ReactExpiration', () => {
724 });
725 });
726
737 - // @gate experimental
727 it('flushSync should not affect expired work', async () => {
728 let setA;
729 let setB;
@@ -778,7 +767,6 @@ describe('ReactExpiration', () => {
767 });
768 });
769
781 - // @gate experimental
770 it('passive effects of expired update flush after paint', async () => {
771 function App({step}) {
772 useEffect(() => {
packages/react-reconciler/src/__tests__/ReactFlushSync-test.js
+2 -4
@@ -14,7 +14,7 @@ describe('ReactFlushSync', () => {
14 Scheduler = require('scheduler');
15 useState = React.useState;
16 useEffect = React.useEffect;
17 - startTransition = React.unstable_startTransition;
17 + startTransition = React.startTransition;
18 });
19
20 function Text({text}) {
@@ -22,7 +22,6 @@ describe('ReactFlushSync', () => {
22 return text;
23 }
24
25 - // @gate experimental || !enableSyncDefaultUpdates
25 test('changes priority of updates in useEffect', async () => {
26 function App() {
27 const [syncState, setSyncState] = useState(0);
@@ -39,7 +38,7 @@ describe('ReactFlushSync', () => {
38 const root = ReactNoop.createRoot();
39 await ReactNoop.act(async () => {
40 if (gate(flags => flags.enableSyncDefaultUpdates)) {
42 - React.unstable_startTransition(() => {
41 + React.startTransition(() => {
42 root.render(<App />);
43 });
44 } else {
@@ -64,7 +63,6 @@ describe('ReactFlushSync', () => {
63 expect(root).toMatchRenderedOutput('1, 1');
64 });
65
67 - // @gate experimental
66 test('nested with startTransition', async () => {
67 let setSyncState;
68 let setState;
packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js
+13 -21
@@ -52,8 +52,8 @@ describe('ReactHooksWithNoopRenderer', () => {
52 useImperativeHandle = React.useImperativeHandle;
53 forwardRef = React.forwardRef;
54 memo = React.memo;
55 - useTransition = React.unstable_useTransition;
56 - useDeferredValue = React.unstable_useDeferredValue;
55 + useTransition = React.useTransition;
56 + useDeferredValue = React.useDeferredValue;
57 Suspense = React.Suspense;
58 act = ReactNoop.act;
59 ContinuousEventPriority = require('react-reconciler/constants')
@@ -149,7 +149,6 @@ describe('ReactHooksWithNoopRenderer', () => {
149 return Promise.resolve().then(() => {});
150 }
151
152 - // @gate experimental || !enableSyncDefaultUpdates
152 it('resumes after an interruption', () => {
153 function Counter(props, ref) {
154 const [count, updateCount] = useState(0);
@@ -166,7 +165,7 @@ describe('ReactHooksWithNoopRenderer', () => {
165
166 // Schedule some updates
167 if (gate(flags => flags.enableSyncDefaultUpdates)) {
169 - React.unstable_startTransition(() => {
168 + React.startTransition(() => {
169 // TODO: Batched updates need to be inside startTransition?
170 ReactNoop.batchedUpdates(() => {
171 counter.current.updateCount(1);
@@ -691,7 +690,6 @@ describe('ReactHooksWithNoopRenderer', () => {
690 expect(ReactNoop.getChildren()).toEqual([span(22)]);
691 });
692
694 - // @gate experimental || !enableSyncDefaultUpdates
693 it('discards render phase updates if something suspends', async () => {
694 const thenable = {then() {}};
695 function Foo({signal}) {
@@ -728,7 +726,7 @@ describe('ReactHooksWithNoopRenderer', () => {
726 expect(root).toMatchRenderedOutput(<span prop={0} />);
727
728 if (gate(flags => flags.enableSyncDefaultUpdates)) {
731 - React.unstable_startTransition(() => {
729 + React.startTransition(() => {
730 root.render(<Foo signal={false} />);
731 });
732 } else {
@@ -739,7 +737,7 @@ describe('ReactHooksWithNoopRenderer', () => {
737
738 // Rendering again should suspend again.
739 if (gate(flags => flags.enableSyncDefaultUpdates)) {
742 - React.unstable_startTransition(() => {
740 + React.startTransition(() => {
741 root.render(<Foo signal={false} />);
742 });
743 } else {
@@ -748,7 +746,6 @@ describe('ReactHooksWithNoopRenderer', () => {
746 expect(Scheduler).toFlushAndYield(['Suspend!']);
747 });
748
751 - // @gate experimental || !enableSyncDefaultUpdates
749 it('discards render phase updates if something suspends, but not other updates in the same component', async () => {
750 const thenable = {then() {}};
751 function Foo({signal}) {
@@ -792,7 +789,7 @@ describe('ReactHooksWithNoopRenderer', () => {
789
790 await ReactNoop.act(async () => {
791 if (gate(flags => flags.enableSyncDefaultUpdates)) {
795 - React.unstable_startTransition(() => {
792 + React.startTransition(() => {
793 root.render(<Foo signal={false} />);
794 setLabel('B');
795 });
@@ -806,7 +803,7 @@ describe('ReactHooksWithNoopRenderer', () => {
803
804 // Rendering again should suspend again.
805 if (gate(flags => flags.enableSyncDefaultUpdates)) {
809 - React.unstable_startTransition(() => {
806 + React.startTransition(() => {
807 root.render(<Foo signal={false} />);
808 });
809 } else {
@@ -817,7 +814,7 @@ describe('ReactHooksWithNoopRenderer', () => {
814 // Flip the signal back to "cancel" the update. However, the update to
815 // label should still proceed. It shouldn't have been dropped.
816 if (gate(flags => flags.enableSyncDefaultUpdates)) {
820 - React.unstable_startTransition(() => {
817 + React.startTransition(() => {
818 root.render(<Foo signal={true} />);
819 });
820 } else {
@@ -864,13 +861,12 @@ describe('ReactHooksWithNoopRenderer', () => {
861 });
862
863 // TODO: This should probably warn
867 - // @gate experimental
864 it('calling startTransition inside render phase', async () => {
865 function App() {
866 const [counter, setCounter] = useState(0);
867
868 if (counter === 0) {
873 - React.unstable_startTransition(() => {
869 + React.startTransition(() => {
870 setCounter(c => c + 1);
871 });
872 }
@@ -1315,7 +1311,6 @@ describe('ReactHooksWithNoopRenderer', () => {
1311 });
1312 });
1313
1318 - // @gate experimental || !enableSyncDefaultUpdates
1314 it('does not warn about state updates for unmounted components with pending passive unmounts for alternates', () => {
1315 let setParentState = null;
1316 const setChildStates = [];
@@ -1383,7 +1378,7 @@ describe('ReactHooksWithNoopRenderer', () => {
1378
1379 // Schedule another update for children, and partially process it.
1380 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1386 - React.unstable_startTransition(() => {
1381 + React.startTransition(() => {
1382 setChildStates.forEach(setChildState => setChildState(2));
1383 });
1384 } else {
@@ -1685,7 +1680,6 @@ describe('ReactHooksWithNoopRenderer', () => {
1680 });
1681 });
1682
1688 - // @gate experimental || !enableSyncDefaultUpdates
1683 it('updates have async priority even if effects are flushed early', () => {
1684 function Counter(props) {
1685 const [count, updateCount] = useState('(empty)');
@@ -1707,7 +1701,7 @@ describe('ReactHooksWithNoopRenderer', () => {
1701
1702 // Rendering again should flush the previous commit's effects
1703 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1710 - React.unstable_startTransition(() => {
1704 + React.startTransition(() => {
1705 ReactNoop.render(<Counter count={1} />, () =>
1706 Scheduler.unstable_yieldValue('Sync effect'),
1707 );
@@ -3127,8 +3121,8 @@ describe('ReactHooksWithNoopRenderer', () => {
3121 expect(totalRefUpdates).toBe(2); // Should not increase since last time
3122 });
3123 });
3124 +
3125 describe('useTransition', () => {
3131 - // @gate experimental
3126 it('delays showing loading state until after timeout', async () => {
3127 let transition;
3128 function App() {
@@ -3190,7 +3184,6 @@ describe('ReactHooksWithNoopRenderer', () => {
3184 });
3185
3186 describe('useDeferredValue', () => {
3193 - // @gate experimental
3187 it('defers text value', async () => {
3188 function TextBox({text}) {
3189 return <AsyncText text={text} />;
@@ -3694,9 +3687,8 @@ describe('ReactHooksWithNoopRenderer', () => {
3687 ]);
3688 });
3689
3697 - // @gate experimental
3690 it('regression: SuspenseList causes unmounts to be dropped on deletion', async () => {
3699 - const SuspenseList = React.unstable_SuspenseList;
3691 + const SuspenseList = React.SuspenseList;
3692
3693 function Row({label}) {
3694 useEffect(() => {
packages/react-reconciler/src/__tests__/ReactIncremental-test.js
+10 -17
@@ -50,7 +50,6 @@ describe('ReactIncremental', () => {
50 expect(Scheduler).toFlushWithoutYielding();
51 });
52
53 - // @gate experimental || !enableSyncDefaultUpdates
53 it('should render a simple component, in steps if needed', () => {
54 function Bar() {
55 Scheduler.unstable_yieldValue('Bar');
@@ -67,7 +66,7 @@ describe('ReactIncremental', () => {
66 }
67
68 if (gate(flags => flags.enableSyncDefaultUpdates)) {
70 - React.unstable_startTransition(() => {
69 + React.startTransition(() => {
70 ReactNoop.render(<Foo />, () =>
71 Scheduler.unstable_yieldValue('callback'),
72 );
@@ -143,7 +142,6 @@ describe('ReactIncremental', () => {
142 ]);
143 });
144
146 - // @gate experimental || !enableSyncDefaultUpdates
145 it('can cancel partially rendered work and restart', () => {
146 function Bar(props) {
147 Scheduler.unstable_yieldValue('Bar');
@@ -165,7 +163,7 @@ describe('ReactIncremental', () => {
163 expect(Scheduler).toFlushAndYield(['Foo', 'Bar', 'Bar']);
164
165 if (gate(flags => flags.enableSyncDefaultUpdates)) {
168 - React.unstable_startTransition(() => {
166 + React.startTransition(() => {
167 ReactNoop.render(<Foo text="bar" />);
168 });
169 } else {
@@ -178,7 +176,7 @@ describe('ReactIncremental', () => {
176 ReactNoop.flushSync(() => ReactNoop.render(null));
177
178 if (gate(flags => flags.enableSyncDefaultUpdates)) {
181 - React.unstable_startTransition(() => {
179 + React.startTransition(() => {
180 ReactNoop.render(<Foo text="baz" />);
181 });
182 } else {
@@ -192,7 +190,6 @@ describe('ReactIncremental', () => {
190 expect(Scheduler).toFlushAndYield(['Bar']);
191 });
192
195 - // @gate experimental || !enableSyncDefaultUpdates
193 it('should call callbacks even if updates are aborted', () => {
194 let inst;
195
@@ -219,7 +216,7 @@ describe('ReactIncremental', () => {
216 expect(Scheduler).toFlushWithoutYielding();
217
218 if (gate(flags => flags.enableSyncDefaultUpdates)) {
222 - React.unstable_startTransition(() => {
219 + React.startTransition(() => {
220 inst.setState(
221 () => {
222 Scheduler.unstable_yieldValue('setState1');
@@ -244,7 +241,7 @@ describe('ReactIncremental', () => {
241 // This will abort the previous work and restart
242 ReactNoop.flushSync(() => ReactNoop.render(<Foo />));
243 if (gate(flags => flags.enableSyncDefaultUpdates)) {
247 - React.unstable_startTransition(() => {
244 + React.startTransition(() => {
245 inst.setState(
246 () => {
247 Scheduler.unstable_yieldValue('setState2');
@@ -1764,7 +1761,6 @@ describe('ReactIncremental', () => {
1761 expect(instance.state.n).toEqual(3);
1762 });
1763
1767 - // @gate experimental || !enableSyncDefaultUpdates
1764 it('merges and masks context', () => {
1765 class Intl extends React.Component {
1766 static childContextTypes = {
@@ -1883,7 +1879,7 @@ describe('ReactIncremental', () => {
1879 'ShowBoth {"locale":"de"}',
1880 ]);
1881 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1886 - React.unstable_startTransition(() => {
1882 + React.startTransition(() => {
1883 ReactNoop.render(
1884 <Intl locale="sv">
1885 <ShowLocale />
@@ -2033,7 +2029,7 @@ describe('ReactIncremental', () => {
2029 }
2030
2031 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2036 - React.unstable_startTransition(() => {
2032 + React.startTransition(() => {
2033 ReactNoop.render(
2034 <Intl locale="fr">
2035 <ShowLocale />
@@ -2739,7 +2735,6 @@ describe('ReactIncremental', () => {
2735 expect(Scheduler).toFlushAndYield(['count:1, name:not brian']);
2736 });
2737
2742 - // @gate experimental || !enableSyncDefaultUpdates
2738 it('does not interrupt for update at same priority', () => {
2739 function Parent(props) {
2740 Scheduler.unstable_yieldValue('Parent: ' + props.step);
@@ -2752,7 +2747,7 @@ describe('ReactIncremental', () => {
2747 }
2748
2749 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2755 - React.unstable_startTransition(() => {
2750 + React.startTransition(() => {
2751 ReactNoop.render(<Parent step={1} />);
2752 });
2753 } else {
@@ -2766,7 +2761,6 @@ describe('ReactIncremental', () => {
2761 expect(Scheduler).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']);
2762 });
2763
2769 - // @gate experimental || !enableSyncDefaultUpdates
2764 it('does not interrupt for update at lower priority', () => {
2765 function Parent(props) {
2766 Scheduler.unstable_yieldValue('Parent: ' + props.step);
@@ -2779,7 +2773,7 @@ describe('ReactIncremental', () => {
2773 }
2774
2775 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2782 - React.unstable_startTransition(() => {
2776 + React.startTransition(() => {
2777 ReactNoop.render(<Parent step={1} />);
2778 });
2779 } else {
@@ -2794,7 +2788,6 @@ describe('ReactIncremental', () => {
2788 expect(Scheduler).toFlushAndYield(['Child: 1', 'Parent: 2', 'Child: 2']);
2789 });
2790
2797 - // @gate experimental || !enableSyncDefaultUpdates
2791 it('does interrupt for update at higher priority', () => {
2792 function Parent(props) {
2793 Scheduler.unstable_yieldValue('Parent: ' + props.step);
@@ -2807,7 +2800,7 @@ describe('ReactIncremental', () => {
2800 }
2801
2802 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2810 - React.unstable_startTransition(() => {
2803 + React.startTransition(() => {
2804 ReactNoop.render(<Parent step={1} />);
2805 });
2806 } else {
packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js
+13 -22
@@ -58,7 +58,6 @@ describe('ReactIncrementalErrorHandling', () => {
58 );
59 }
60
61 - // @gate experimental || !enableSyncDefaultUpdates
61 it('recovers from errors asynchronously', () => {
62 class ErrorBoundary extends React.Component {
63 state = {error: null};
@@ -92,7 +91,7 @@ describe('ReactIncrementalErrorHandling', () => {
91 }
92
93 if (gate(flags => flags.enableSyncDefaultUpdates)) {
95 - React.unstable_startTransition(() => {
94 + React.startTransition(() => {
95 ReactNoop.render(
96 <ErrorBoundary>
97 <Indirection>
@@ -171,7 +170,6 @@ describe('ReactIncrementalErrorHandling', () => {
170 expect(ReactNoop.getChildren()).toEqual([span('Caught an error: oops!')]);
171 });
172
174 - // @gate experimental || !enableSyncDefaultUpdates
173 it('recovers from errors asynchronously (legacy, no getDerivedStateFromError)', () => {
174 class ErrorBoundary extends React.Component {
175 state = {error: null};
@@ -205,7 +203,7 @@ describe('ReactIncrementalErrorHandling', () => {
203 }
204
205 if (gate(flags => flags.enableSyncDefaultUpdates)) {
208 - React.unstable_startTransition(() => {
206 + React.startTransition(() => {
207 ReactNoop.render(
208 <ErrorBoundary>
209 <Indirection>
@@ -270,7 +268,6 @@ describe('ReactIncrementalErrorHandling', () => {
268 expect(ReactNoop.getChildren()).toEqual([span('Caught an error: oops!')]);
269 });
270
273 - // @gate experimental
271 it("retries at a lower priority if there's additional pending work", async () => {
272 function App(props) {
273 if (props.isBroken) {
@@ -285,12 +282,12 @@ describe('ReactIncrementalErrorHandling', () => {
282 Scheduler.unstable_yieldValue('commit');
283 }
284
288 - React.unstable_startTransition(() => {
285 + React.startTransition(() => {
286 ReactNoop.render(<App isBroken={true} />, onCommit);
287 });
288 expect(Scheduler).toFlushAndYieldThrough(['error']);
289
293 - React.unstable_startTransition(() => {
290 + React.startTransition(() => {
291 // This update is in a separate batch
292 ReactNoop.render(<App isBroken={false} />, onCommit);
293 });
@@ -333,14 +330,14 @@ describe('ReactIncrementalErrorHandling', () => {
330 Scheduler.unstable_yieldValue('commit');
331 }
332
336 - React.unstable_startTransition(() => {
333 + React.startTransition(() => {
334 ReactNoop.render(<App isBroken={true} />, onCommit);
335 });
336 expect(Scheduler).toFlushAndYieldThrough(['error']);
337
338 expect(ReactNoop).toMatchRenderedOutput(null);
339
343 - React.unstable_startTransition(() => {
340 + React.startTransition(() => {
341 // This update is in a separate batch
342 ReactNoop.render(<App isBroken={false} />, onCommit);
343 });
@@ -378,7 +375,6 @@ describe('ReactIncrementalErrorHandling', () => {
375 );
376 });
377
381 - // @gate experimental || !enableSyncDefaultUpdates
378 it('retries one more time before handling error', () => {
379 function BadRender({unused}) {
380 Scheduler.unstable_yieldValue('BadRender');
@@ -401,7 +397,7 @@ describe('ReactIncrementalErrorHandling', () => {
397 }
398
399 if (gate(flags => flags.enableSyncDefaultUpdates)) {
404 - React.unstable_startTransition(() => {
400 + React.startTransition(() => {
401 ReactNoop.render(<Parent />, () =>
402 Scheduler.unstable_yieldValue('commit'),
403 );
@@ -429,7 +425,6 @@ describe('ReactIncrementalErrorHandling', () => {
425 expect(ReactNoop.getChildren()).toEqual([]);
426 });
427
432 - // @gate experimental || !enableSyncDefaultUpdates
428 it('retries one more time if an error occurs during a render that expires midway through the tree', async () => {
429 function Oops({unused}) {
430 Scheduler.unstable_yieldValue('Oops');
@@ -454,7 +449,7 @@ describe('ReactIncrementalErrorHandling', () => {
449 }
450
451 if (gate(flags => flags.enableSyncDefaultUpdates)) {
457 - React.unstable_startTransition(() => {
452 + React.startTransition(() => {
453 ReactNoop.render(<App />);
454 });
455 } else {
@@ -566,7 +561,6 @@ describe('ReactIncrementalErrorHandling', () => {
561 expect(ReactNoop.getChildren()).toEqual([span('Caught an error: Hello.')]);
562 });
563
569 - // @gate experimental || !enableSyncDefaultUpdates
564 it('catches render error in a boundary during partial deferred mounting', () => {
565 class ErrorBoundary extends React.Component {
566 state = {error: null};
@@ -592,7 +586,7 @@ describe('ReactIncrementalErrorHandling', () => {
586 }
587
588 if (gate(flags => flags.enableSyncDefaultUpdates)) {
595 - React.unstable_startTransition(() => {
589 + React.startTransition(() => {
590 ReactNoop.render(
591 <ErrorBoundary>
592 <BrokenRender />
@@ -757,7 +751,6 @@ describe('ReactIncrementalErrorHandling', () => {
751 expect(ReactNoop.getChildren()).toEqual([]);
752 });
753
760 - // @gate experimental || !enableSyncDefaultUpdates
754 it('propagates an error from a noop error boundary during partial deferred mounting', () => {
755 class RethrowErrorBoundary extends React.Component {
756 componentDidCatch(error) {
@@ -776,7 +769,7 @@ describe('ReactIncrementalErrorHandling', () => {
769 }
770
771 if (gate(flags => flags.enableSyncDefaultUpdates)) {
779 - React.unstable_startTransition(() => {
772 + React.startTransition(() => {
773 ReactNoop.render(
774 <RethrowErrorBoundary>
775 <BrokenRender />
@@ -1842,7 +1835,6 @@ describe('ReactIncrementalErrorHandling', () => {
1835 });
1836 }
1837
1845 - // @gate experimental
1838 it('uncaught errors should be discarded if the render is aborted', async () => {
1839 const root = ReactNoop.createRoot();
1840
@@ -1853,7 +1845,7 @@ describe('ReactIncrementalErrorHandling', () => {
1845
1846 await ReactNoop.act(async () => {
1847 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1856 - React.unstable_startTransition(() => {
1848 + React.startTransition(() => {
1849 root.render(<Oops />);
1850 });
1851 } else {
@@ -1866,7 +1858,7 @@ describe('ReactIncrementalErrorHandling', () => {
1858 // Interleaved update. When the root completes, instead of throwing the
1859 // error, it should try rendering again. This update will cause it to
1860 // recover gracefully.
1869 - React.unstable_startTransition(() => {
1861 + React.startTransition(() => {
1862 root.render('Everything is fine.');
1863 });
1864 });
@@ -1875,7 +1867,6 @@ describe('ReactIncrementalErrorHandling', () => {
1867 expect(root).toMatchRenderedOutput('Everything is fine.');
1868 });
1869
1878 - // @gate experimental
1870 it('uncaught errors are discarded if the render is aborted, case 2', async () => {
1871 const {useState} = React;
1872 const root = ReactNoop.createRoot();
@@ -1902,7 +1893,7 @@ describe('ReactIncrementalErrorHandling', () => {
1893 await ReactNoop.act(async () => {
1894 // Schedule a default pri and a low pri update on the root.
1895 root.render(<Oops />);
1905 - React.unstable_startTransition(() => {
1896 + React.startTransition(() => {
1897 root.render(<AllGood />);
1898 });
1899
packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.js
+5 -8
@@ -34,7 +34,6 @@ describe('ReactIncrementalReflection', () => {
34 return {type: 'span', children: [], prop, hidden: false};
35 }
36
37 - // @gate experimental || !enableSyncDefaultUpdates
37 it('handles isMounted even when the initial render is deferred', () => {
38 const instances = [];
39
@@ -65,7 +64,7 @@ describe('ReactIncrementalReflection', () => {
64 }
65
66 if (gate(flags => flags.enableSyncDefaultUpdates)) {
68 - React.unstable_startTransition(() => {
67 + React.startTransition(() => {
68 ReactNoop.render(<Foo />);
69 });
70 } else {
@@ -83,7 +82,6 @@ describe('ReactIncrementalReflection', () => {
82 expect(instances[0]._isMounted()).toBe(true);
83 });
84
86 - // @gate experimental || !enableSyncDefaultUpdates
85 it('handles isMounted when an unmount is deferred', () => {
86 const instances = [];
87
@@ -120,7 +118,7 @@ describe('ReactIncrementalReflection', () => {
118 expect(instances[0]._isMounted()).toBe(true);
119
120 if (gate(flags => flags.enableSyncDefaultUpdates)) {
123 - React.unstable_startTransition(() => {
121 + React.startTransition(() => {
122 ReactNoop.render(<Foo mount={false} />);
123 });
124 } else {
@@ -138,7 +136,6 @@ describe('ReactIncrementalReflection', () => {
136 expect(instances[0]._isMounted()).toBe(false);
137 });
138
141 - // @gate experimental || !enableSyncDefaultUpdates
139 it('finds no node before insertion and correct node before deletion', () => {
140 let classInstance = null;
141
@@ -210,7 +207,7 @@ describe('ReactIncrementalReflection', () => {
207 }
208
209 if (gate(flags => flags.enableSyncDefaultUpdates)) {
213 - React.unstable_startTransition(() => {
210 + React.startTransition(() => {
211 ReactNoop.render(<Foo step={0} />);
212 });
213 } else {
@@ -250,7 +247,7 @@ describe('ReactIncrementalReflection', () => {
247 // The next step will render a new host node but won't get committed yet.
248 // We expect this to mutate the original Fiber.
249 if (gate(flags => flags.enableSyncDefaultUpdates)) {
253 - React.unstable_startTransition(() => {
250 + React.startTransition(() => {
251 ReactNoop.render(<Foo step={2} />);
252 });
253 } else {
@@ -277,7 +274,7 @@ describe('ReactIncrementalReflection', () => {
274
275 // Render to null but don't commit it yet.
276 if (gate(flags => flags.enableSyncDefaultUpdates)) {
280 - React.unstable_startTransition(() => {
277 + React.startTransition(() => {
278 ReactNoop.render(<Foo step={3} />);
279 });
280 } else {
packages/react-reconciler/src/__tests__/ReactIncrementalScheduling-test.js
+6 -10
@@ -85,7 +85,6 @@ describe('ReactIncrementalScheduling', () => {
85 expect(ReactNoop).toMatchRenderedOutput(<span prop={5} />);
86 });
87
88 - // @gate experimental || !enableSyncDefaultUpdates
88 it('works on deferred roots in the order they were scheduled', () => {
89 const {useEffect} = React;
90 function Text({text}) {
@@ -109,7 +108,7 @@ describe('ReactIncrementalScheduling', () => {
108 // Schedule deferred work in the reverse order
109 ReactNoop.act(() => {
110 if (gate(flags => flags.enableSyncDefaultUpdates)) {
112 - React.unstable_startTransition(() => {
111 + React.startTransition(() => {
112 ReactNoop.renderToRootWithID(<Text text="c:2" />, 'c');
113 ReactNoop.renderToRootWithID(<Text text="b:2" />, 'b');
114 });
@@ -126,7 +125,7 @@ describe('ReactIncrementalScheduling', () => {
125 // Schedule last bit of work, it will get processed the last
126
127 if (gate(flags => flags.enableSyncDefaultUpdates)) {
129 - React.unstable_startTransition(() => {
128 + React.startTransition(() => {
129 ReactNoop.renderToRootWithID(<Text text="a:2" />, 'a');
130 });
131 } else {
@@ -146,7 +145,6 @@ describe('ReactIncrementalScheduling', () => {
145 });
146 });
147
149 - // @gate experimental || !enableSyncDefaultUpdates
148 it('schedules sync updates when inside componentDidMount/Update', () => {
149 let instance;
150
@@ -186,7 +184,7 @@ describe('ReactIncrementalScheduling', () => {
184 }
185
186 if (gate(flags => flags.enableSyncDefaultUpdates)) {
189 - React.unstable_startTransition(() => {
187 + React.startTransition(() => {
188 ReactNoop.render(<Foo />);
189 });
190 } else {
@@ -206,7 +204,7 @@ describe('ReactIncrementalScheduling', () => {
204 ]);
205
206 if (gate(flags => flags.enableSyncDefaultUpdates)) {
209 - React.unstable_startTransition(() => {
207 + React.startTransition(() => {
208 instance.setState({tick: 2});
209 });
210 } else {
@@ -224,7 +222,6 @@ describe('ReactIncrementalScheduling', () => {
222 ]);
223 });
224
227 - // @gate experimental || !enableSyncDefaultUpdates
225 it('can opt-in to async scheduling inside componentDidMount/Update', () => {
226 let instance;
227 class Foo extends React.Component {
@@ -284,7 +281,7 @@ describe('ReactIncrementalScheduling', () => {
281 // Increment the tick to 2. This will trigger an update inside cDU. Flush
282 // the first update without flushing the second one.
283 if (gate(flags => flags.enableSyncDefaultUpdates)) {
287 - React.unstable_startTransition(() => {
284 + React.startTransition(() => {
285 instance.setState({tick: 2});
286 });
287
@@ -315,7 +312,6 @@ describe('ReactIncrementalScheduling', () => {
312 }
313 });
314
318 - // @gate experimental || !enableSyncDefaultUpdates
315 it('performs Task work even after time runs out', () => {
316 class Foo extends React.Component {
317 state = {step: 1};
@@ -334,7 +330,7 @@ describe('ReactIncrementalScheduling', () => {
330 }
331 }
332 if (gate(flags => flags.enableSyncDefaultUpdates)) {
337 - React.unstable_startTransition(() => {
333 + React.startTransition(() => {
334 ReactNoop.render(<Foo />);
335 });
336 } else {
packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js
+4 -6
@@ -384,7 +384,6 @@ describe('ReactIncrementalSideEffects', () => {
384 expect(ReactNoop.getChildren('portalContainer')).toEqual([]);
385 });
386
387 - // @gate experimental || !enableSyncDefaultUpdates
387 it('does not update child nodes if a flush is aborted', () => {
388 function Bar(props) {
389 Scheduler.unstable_yieldValue('Bar');
@@ -411,7 +410,7 @@ describe('ReactIncrementalSideEffects', () => {
410 ]);
411
412 if (gate(flags => flags.enableSyncDefaultUpdates)) {
414 - React.unstable_startTransition(() => {
413 + React.startTransition(() => {
414 ReactNoop.render(<Foo text="World" />);
415 });
416 } else {
@@ -640,14 +639,13 @@ describe('ReactIncrementalSideEffects', () => {
639 );
640 });
641
643 - // @gate experimental || !enableSyncDefaultUpdates
642 it('can update a completed tree before it has a chance to commit', () => {
643 function Foo(props) {
644 Scheduler.unstable_yieldValue('Foo');
645 return <span prop={props.step} />;
646 }
647 if (gate(flags => flags.enableSyncDefaultUpdates)) {
650 - React.unstable_startTransition(() => {
648 + React.startTransition(() => {
649 ReactNoop.render(<Foo step={1} />);
650 });
651 } else {
@@ -662,7 +660,7 @@ describe('ReactIncrementalSideEffects', () => {
660 expect(ReactNoop.getChildrenAsJSX()).toEqual(<span prop={1} />);
661
662 if (gate(flags => flags.enableSyncDefaultUpdates)) {
665 - React.unstable_startTransition(() => {
663 + React.startTransition(() => {
664 ReactNoop.render(<Foo step={2} />);
665 });
666 } else {
@@ -675,7 +673,7 @@ describe('ReactIncrementalSideEffects', () => {
673 // new props
674
675 if (gate(flags => flags.enableSyncDefaultUpdates)) {
678 - React.unstable_startTransition(() => {
676 + React.startTransition(() => {
677 ReactNoop.render(<Foo step={3} />);
678 });
679 } else {
packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js
+11 -18
@@ -131,7 +131,6 @@ describe('ReactIncrementalUpdates', () => {
131 expect(instance.state).toEqual({c: 'c', d: 'd'});
132 });
133
134 - // @gate experimental || !enableSyncDefaultUpdates
134 it('can abort an update, schedule additional updates, and resume', () => {
135 let instance;
136 class Foo extends React.Component {
@@ -162,7 +161,7 @@ describe('ReactIncrementalUpdates', () => {
161
162 // Schedule some async updates
163 if (gate(flags => flags.enableSyncDefaultUpdates)) {
165 - React.unstable_startTransition(() => {
164 + React.startTransition(() => {
165 instance.setState(createUpdate('a'));
166 instance.setState(createUpdate('b'));
167 instance.setState(createUpdate('c'));
@@ -184,7 +183,7 @@ describe('ReactIncrementalUpdates', () => {
183 instance.setState(createUpdate('e'));
184 instance.setState(createUpdate('f'));
185 });
187 - React.unstable_startTransition(() => {
186 + React.startTransition(() => {
187 instance.setState(createUpdate('g'));
188 });
189
@@ -229,7 +228,6 @@ describe('ReactIncrementalUpdates', () => {
228 }
229 });
230
232 - // @gate experimental || !enableSyncDefaultUpdates
231 it('can abort an update, schedule a replaceState, and resume', () => {
232 let instance;
233 class Foo extends React.Component {
@@ -260,7 +258,7 @@ describe('ReactIncrementalUpdates', () => {
258
259 // Schedule some async updates
260 if (gate(flags => flags.enableSyncDefaultUpdates)) {
263 - React.unstable_startTransition(() => {
261 + React.startTransition(() => {
262 instance.setState(createUpdate('a'));
263 instance.setState(createUpdate('b'));
264 instance.setState(createUpdate('c'));
@@ -285,7 +283,7 @@ describe('ReactIncrementalUpdates', () => {
283 // reaching into the updater.
284 instance.updater.enqueueReplaceState(instance, createUpdate('f'));
285 });
288 - React.unstable_startTransition(() => {
286 + React.startTransition(() => {
287 instance.setState(createUpdate('g'));
288 });
289
@@ -543,7 +541,6 @@ describe('ReactIncrementalUpdates', () => {
541 expect(ReactNoop.getChildren()).toEqual([span('derived state')]);
542 });
543
546 - // @gate experimental || !enableSyncDefaultUpdates
544 it('regression: does not expire soon due to layout effects in the last batch', () => {
545 const {useState, useLayoutEffect} = React;
546
@@ -561,7 +558,7 @@ describe('ReactIncrementalUpdates', () => {
558
559 ReactNoop.act(() => {
560 if (gate(flags => flags.enableSyncDefaultUpdates)) {
564 - React.unstable_startTransition(() => {
561 + React.startTransition(() => {
562 ReactNoop.render(<App />);
563 });
564 } else {
@@ -577,7 +574,7 @@ describe('ReactIncrementalUpdates', () => {
574
575 Scheduler.unstable_advanceTime(10000);
576 if (gate(flags => flags.enableSyncDefaultUpdates)) {
580 - React.unstable_startTransition(() => {
577 + React.startTransition(() => {
578 setCount(2);
579 });
580 } else {
@@ -588,7 +585,6 @@ describe('ReactIncrementalUpdates', () => {
585 });
586 });
587
591 - // @gate experimental || !enableSyncDefaultUpdates
588 it('regression: does not expire soon due to previous flushSync', () => {
589 function Text({text}) {
590 Scheduler.unstable_yieldValue(text);
@@ -603,7 +599,7 @@ describe('ReactIncrementalUpdates', () => {
599 Scheduler.unstable_advanceTime(10000);
600
601 if (gate(flags => flags.enableSyncDefaultUpdates)) {
606 - React.unstable_startTransition(() => {
602 + React.startTransition(() => {
603 ReactNoop.render(<Text text="B" />);
604 });
605 } else {
@@ -613,7 +609,6 @@ describe('ReactIncrementalUpdates', () => {
609 expect(Scheduler).toHaveYielded([]);
610 });
611
616 - // @gate experimental || !enableSyncDefaultUpdates
612 it('regression: does not expire soon due to previous expired work', () => {
613 function Text({text}) {
614 Scheduler.unstable_yieldValue(text);
@@ -621,7 +616,7 @@ describe('ReactIncrementalUpdates', () => {
616 }
617
618 if (gate(flags => flags.enableSyncDefaultUpdates)) {
624 - React.unstable_startTransition(() => {
619 + React.startTransition(() => {
620 ReactNoop.render(<Text text="A" />);
621 });
622 } else {
@@ -634,7 +629,7 @@ describe('ReactIncrementalUpdates', () => {
629 Scheduler.unstable_advanceTime(10000);
630
631 if (gate(flags => flags.enableSyncDefaultUpdates)) {
637 - React.unstable_startTransition(() => {
632 + React.startTransition(() => {
633 ReactNoop.render(<Text text="B" />);
634 });
635 } else {
@@ -644,7 +639,6 @@ describe('ReactIncrementalUpdates', () => {
639 expect(Scheduler).toHaveYielded([]);
640 });
641
647 - // @gate experimental || !enableSyncDefaultUpdates
642 it('when rebasing, does not exclude updates that were already committed, regardless of priority', async () => {
643 const {useState, useLayoutEffect} = React;
644
@@ -678,7 +672,7 @@ describe('ReactIncrementalUpdates', () => {
672
673 await ReactNoop.act(async () => {
674 if (gate(flags => flags.enableSyncDefaultUpdates)) {
681 - React.unstable_startTransition(() => {
675 + React.startTransition(() => {
676 pushToLog('A');
677 });
678 } else {
@@ -707,7 +701,6 @@ describe('ReactIncrementalUpdates', () => {
701 expect(root).toMatchRenderedOutput('ABCD');
702 });
703
710 - // @gate experimental || !enableSyncDefaultUpdates
704 it('when rebasing, does not exclude updates that were already committed, regardless of priority (classes)', async () => {
705 let pushToLog;
706 class App extends React.Component {
@@ -740,7 +733,7 @@ describe('ReactIncrementalUpdates', () => {
733
734 await ReactNoop.act(async () => {
735 if (gate(flags => flags.enableSyncDefaultUpdates)) {
743 - React.unstable_startTransition(() => {
736 + React.startTransition(() => {
737 pushToLog('A');
738 });
739 } else {
packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js
+3 -5
@@ -12,7 +12,7 @@ describe('ReactInterleavedUpdates', () => {
12 React = require('react');
13 ReactNoop = require('react-noop-renderer');
14 Scheduler = require('scheduler');
15 - startTransition = React.unstable_startTransition;
15 + startTransition = React.startTransition;
16 useState = React.useState;
17 useEffect = React.useEffect;
18 });
@@ -22,7 +22,6 @@ describe('ReactInterleavedUpdates', () => {
22 return text;
23 }
24
25 - // @gate experimental || !enableSyncDefaultUpdates
25 test('update during an interleaved event is not processed during the current render', async () => {
26 const updaters = [];
27
@@ -57,7 +56,7 @@ describe('ReactInterleavedUpdates', () => {
56
57 await ReactNoop.act(async () => {
58 if (gate(flags => flags.enableSyncDefaultUpdates)) {
60 - React.unstable_startTransition(() => {
59 + React.startTransition(() => {
60 updateChildren(1);
61 });
62 } else {
@@ -69,7 +68,7 @@ describe('ReactInterleavedUpdates', () => {
68 // In an interleaved event, schedule an update on each of the children.
69 // Including the two that haven't rendered yet.
70 if (gate(flags => flags.enableSyncDefaultUpdates)) {
72 - React.unstable_startTransition(() => {
71 + React.startTransition(() => {
72 updateChildren(2);
73 });
74 } else {
@@ -85,7 +84,6 @@ describe('ReactInterleavedUpdates', () => {
84 expect(root).toMatchRenderedOutput('222');
85 });
86
88 - // @gate experimental
87 // @gate !enableSyncDefaultUpdates
88 test('low priority update during an interleaved event is not processed during the current render', async () => {
89 // Same as previous test, but the interleaved update is lower priority than
packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js
+1 -2
@@ -1475,7 +1475,6 @@ describe('ReactLazy', () => {
1475 });
1476
1477 // @gate enableLazyElements
1478 - // @gate experimental || !enableSyncDefaultUpdates
1478 it('mount and reorder lazy elements', async () => {
1479 class Child extends React.Component {
1480 componentDidMount() {
@@ -1536,7 +1535,7 @@ describe('ReactLazy', () => {
1535
1536 // Swap the position of A and B
1537 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1539 - React.unstable_startTransition(() => {
1538 + React.startTransition(() => {
1539 root.update(<Parent swap={true} />);
1540 });
1541 } else {
packages/react-reconciler/src/__tests__/ReactNewContext-test.js
+1 -2
@@ -828,7 +828,6 @@ describe('ReactNewContext', () => {
828 );
829 });
830
831 - // @gate experimental || !enableSyncDefaultUpdates
831 it('warns if multiple renderers concurrently render the same context', () => {
832 spyOnDev(console, 'error');
833 const Context = React.createContext(0);
@@ -848,7 +847,7 @@ describe('ReactNewContext', () => {
847 }
848
849 if (gate(flags => flags.enableSyncDefaultUpdates)) {
851 - React.unstable_startTransition(() => {
850 + React.startTransition(() => {
851 ReactNoop.render(<App value={1} />);
852 });
853 } else {
packages/react-reconciler/src/__tests__/ReactSchedulerIntegration-test.js
+3 -5
@@ -28,7 +28,7 @@ describe('ReactSchedulerIntegration', () => {
28 NormalPriority = Scheduler.unstable_NormalPriority;
29 IdlePriority = Scheduler.unstable_IdlePriority;
30 runWithPriority = Scheduler.unstable_runWithPriority;
31 - startTransition = React.unstable_startTransition;
31 + startTransition = React.startTransition;
32 });
33
34 // Note: This is based on a similar component we use in www. We can delete
@@ -88,7 +88,6 @@ describe('ReactSchedulerIntegration', () => {
88 ]);
89 });
90
91 - // @gate experimental || !enableSyncDefaultUpdates
91 it('requests a paint after committing', () => {
92 const scheduleCallback = Scheduler.unstable_scheduleCallback;
93
@@ -102,7 +101,7 @@ describe('ReactSchedulerIntegration', () => {
101
102 // Schedule a React render. React will request a paint after committing it.
103 if (gate(flags => flags.enableSyncDefaultUpdates)) {
105 - React.unstable_startTransition(() => {
104 + React.startTransition(() => {
105 root.render('Update');
106 });
107 } else {
@@ -203,7 +202,7 @@ describe(
202 React = require('react');
203 ReactNoop = require('react-noop-renderer');
204 Scheduler = require('scheduler');
206 - startTransition = React.unstable_startTransition;
205 + startTransition = React.startTransition;
206 });
207
208 afterEach(() => {
@@ -252,7 +251,6 @@ describe(
251 });
252 });
253
255 - // @gate experimental
254 it('mock Scheduler module to check if `shouldYield` is called', async () => {
255 // This test reproduces a bug where React's Scheduler task timed out but
256 // the `shouldYield` method returned true. Usually we try not to mock
packages/react-reconciler/src/__tests__/ReactSuspense-test.internal.js
+3 -6
@@ -96,7 +96,6 @@ describe('ReactSuspense', () => {
96 }
97 }
98
99 - // @gate experimental || !enableSyncDefaultUpdates
99 it('suspends rendering and continues later', () => {
100 function Bar(props) {
101 Scheduler.unstable_yieldValue('Bar');
@@ -128,7 +127,7 @@ describe('ReactSuspense', () => {
127 // Navigate the shell to now render the child content.
128 // This should suspend.
129 if (gate(flags => flags.enableSyncDefaultUpdates)) {
131 - React.unstable_startTransition(() => {
130 + React.startTransition(() => {
131 root.update(<Foo renderBar={true} />);
132 });
133 } else {
@@ -201,7 +200,6 @@ describe('ReactSuspense', () => {
200 expect(root).toMatchRenderedOutput('AB');
201 });
202
204 - // @gate experimental || !enableSyncDefaultUpdates
203 it('interrupts current render if promise resolves before current render phase', () => {
204 let didResolve = false;
205 const listeners = [];
@@ -244,7 +242,7 @@ describe('ReactSuspense', () => {
242
243 // The update will suspend.
244 if (gate(flags => flags.enableSyncDefaultUpdates)) {
247 - React.unstable_startTransition(() => {
245 + React.startTransition(() => {
246 root.update(
247 <>
248 <Suspense fallback={<Text text="Loading..." />}>
@@ -289,7 +287,6 @@ describe('ReactSuspense', () => {
287 expect(root).toMatchRenderedOutput('AsyncAfter SuspenseSibling');
288 });
289
292 - // @gate experimental
290 // @gate !enableSyncDefaultUpdates
291 it(
292 'interrupts current render when something suspends with a ' +
@@ -331,7 +328,7 @@ describe('ReactSuspense', () => {
328
329 // Schedule another update. This will have lower priority because it's
330 // a transition.
334 - React.unstable_startTransition(() => {
331 + React.startTransition(() => {
332 root.update(<App shouldSuspend={false} step={2} />);
333 });
334
packages/react-reconciler/src/__tests__/ReactSuspenseList-test.js
+7 -44
@@ -14,7 +14,7 @@ describe('ReactSuspenseList', () => {
14 Scheduler = require('scheduler');
15 Profiler = React.Profiler;
16 Suspense = React.Suspense;
17 - SuspenseList = React.unstable_SuspenseList;
17 + SuspenseList = React.SuspenseList;
18 });
19
20 function Text(props) {
@@ -40,7 +40,6 @@ describe('ReactSuspenseList', () => {
40 return Component;
41 }
42
43 - // @gate experimental
43 it('warns if an unsupported revealOrder option is used', () => {
44 function Foo() {
45 return (
@@ -60,7 +59,6 @@ describe('ReactSuspenseList', () => {
59 ]);
60 });
61
63 - // @gate experimental
62 it('warns if a upper case revealOrder option is used', () => {
63 function Foo() {
64 return (
@@ -80,7 +78,6 @@ describe('ReactSuspenseList', () => {
78 ]);
79 });
80
83 - // @gate experimental
81 it('warns if a misspelled revealOrder option is used', () => {
82 function Foo() {
83 return (
@@ -101,7 +98,6 @@ describe('ReactSuspenseList', () => {
98 ]);
99 });
100
104 - // @gate experimental
101 it('warns if a single element is passed to a "forwards" list', () => {
102 function Foo({children}) {
103 return <SuspenseList revealOrder="forwards">{children}</SuspenseList>;
@@ -134,7 +130,6 @@ describe('ReactSuspenseList', () => {
130 ]);
131 });
132
137 - // @gate experimental
133 it('warns if a single fragment is passed to a "backwards" list', () => {
134 function Foo() {
135 return (
@@ -155,7 +150,6 @@ describe('ReactSuspenseList', () => {
150 ]);
151 });
152
158 - // @gate experimental
153 it('warns if a nested array is passed to a "forwards" list', () => {
154 function Foo({items}) {
155 return (
@@ -183,7 +177,6 @@ describe('ReactSuspenseList', () => {
177 ]);
178 });
179
186 - // @gate experimental
180 it('shows content independently by default', async () => {
181 const A = createAsyncText('A');
182 const B = createAsyncText('B');
@@ -250,7 +243,6 @@ describe('ReactSuspenseList', () => {
243 );
244 });
245
253 - // @gate experimental
246 it('shows content independently in legacy mode regardless of option', async () => {
247 const A = createAsyncText('A');
248 const B = createAsyncText('B');
@@ -321,7 +313,6 @@ describe('ReactSuspenseList', () => {
313 );
314 });
315
324 - // @gate experimental
316 it('displays all "together"', async () => {
317 const A = createAsyncText('A');
318 const B = createAsyncText('B');
@@ -391,7 +382,6 @@ describe('ReactSuspenseList', () => {
382 );
383 });
384
394 - // @gate experimental
385 it('displays all "together" even when nested as siblings', async () => {
386 const A = createAsyncText('A');
387 const B = createAsyncText('B');
@@ -477,7 +467,6 @@ describe('ReactSuspenseList', () => {
467 );
468 });
469
480 - // @gate experimental
470 it('displays all "together" in nested SuspenseLists', async () => {
471 const A = createAsyncText('A');
472 const B = createAsyncText('B');
@@ -539,7 +528,6 @@ describe('ReactSuspenseList', () => {
528 );
529 });
530
542 - // @gate experimental
531 it('displays all "together" in nested SuspenseLists where the inner is default', async () => {
532 const A = createAsyncText('A');
533 const B = createAsyncText('B');
@@ -599,7 +587,6 @@ describe('ReactSuspenseList', () => {
587 );
588 });
589
602 - // @gate experimental
590 it('displays all "together" during an update', async () => {
591 const A = createAsyncText('A');
592 const B = createAsyncText('B');
@@ -684,7 +671,6 @@ describe('ReactSuspenseList', () => {
671 );
672 });
673
687 - // @gate experimental
674 it('avoided boundaries can be coordinate with SuspenseList', async () => {
675 const A = createAsyncText('A');
676 const B = createAsyncText('B');
@@ -783,7 +769,6 @@ describe('ReactSuspenseList', () => {
769 );
770 });
771
786 - // @gate experimental
772 it('displays each items in "forwards" order', async () => {
773 const A = createAsyncText('A');
774 const B = createAsyncText('B');
@@ -849,7 +834,6 @@ describe('ReactSuspenseList', () => {
834 );
835 });
836
852 - // @gate experimental
837 it('displays each items in "backwards" order', async () => {
838 const A = createAsyncText('A');
839 const B = createAsyncText('B');
@@ -915,7 +899,6 @@ describe('ReactSuspenseList', () => {
899 );
900 });
901
918 - // @gate experimental
902 it('displays added row at the top "together" and the bottom in "forwards" order', async () => {
903 const A = createAsyncText('A');
904 const B = createAsyncText('B');
@@ -1070,7 +1053,6 @@ describe('ReactSuspenseList', () => {
1053 );
1054 });
1055
1073 - // @gate experimental
1056 it('displays added row at the top "together" and the bottom in "backwards" order', async () => {
1057 const A = createAsyncText('A');
1058 const B = createAsyncText('B');
@@ -1255,7 +1237,6 @@ describe('ReactSuspenseList', () => {
1237 );
1238 });
1239
1258 - // @gate experimental
1240 it('switches to rendering fallbacks if the tail takes long CPU time', async () => {
1241 function Foo() {
1242 return (
@@ -1275,7 +1256,7 @@ describe('ReactSuspenseList', () => {
1256
1257 // This render is only CPU bound. Nothing suspends.
1258 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1278 - React.unstable_startTransition(() => {
1259 + React.startTransition(() => {
1260 ReactNoop.render(<Foo />);
1261 });
1262 } else {
@@ -1324,7 +1305,6 @@ describe('ReactSuspenseList', () => {
1305 );
1306 });
1307
1327 - // @gate experimental
1308 it('only shows one loading state at a time for "collapsed" tail insertions', async () => {
1309 const A = createAsyncText('A');
1310 const B = createAsyncText('B');
@@ -1394,7 +1374,6 @@ describe('ReactSuspenseList', () => {
1374 );
1375 });
1376
1397 - // @gate experimental
1377 it('warns if an unsupported tail option is used', () => {
1378 function Foo() {
1379 return (
@@ -1415,7 +1394,6 @@ describe('ReactSuspenseList', () => {
1394 ]);
1395 });
1396
1418 - // @gate experimental
1397 it('warns if a tail option is used with "together"', () => {
1398 function Foo() {
1399 return (
@@ -1436,7 +1414,6 @@ describe('ReactSuspenseList', () => {
1414 ]);
1415 });
1416
1439 - // @gate experimental
1417 it('renders one "collapsed" fallback even if CPU time elapsed', async () => {
1418 function Foo() {
1419 return (
@@ -1459,7 +1436,7 @@ describe('ReactSuspenseList', () => {
1436
1437 // This render is only CPU bound. Nothing suspends.
1438 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1462 - React.unstable_startTransition(() => {
1439 + React.startTransition(() => {
1440 ReactNoop.render(<Foo />);
1441 });
1442 } else {
@@ -1509,7 +1486,6 @@ describe('ReactSuspenseList', () => {
1486 );
1487 });
1488
1512 - // @gate experimental
1489 it('adding to the middle does not collapse insertions (forwards)', async () => {
1490 const A = createAsyncText('A');
1491 const B = createAsyncText('B');
@@ -1652,7 +1628,6 @@ describe('ReactSuspenseList', () => {
1628 );
1629 });
1630
1655 - // @gate experimental
1631 it('adding to the middle does not collapse insertions (backwards)', async () => {
1632 const A = createAsyncText('A');
1633 const B = createAsyncText('B');
@@ -1800,7 +1775,6 @@ describe('ReactSuspenseList', () => {
1775 );
1776 });
1777
1803 - // @gate experimental
1778 it('adding to the middle of committed tail does not collapse insertions', async () => {
1779 const A = createAsyncText('A');
1780 const B = createAsyncText('B');
@@ -1958,7 +1932,6 @@ describe('ReactSuspenseList', () => {
1932 );
1933 });
1934
1961 - // @gate experimental
1935 it('only shows no initial loading state "hidden" tail insertions', async () => {
1936 const A = createAsyncText('A');
1937 const B = createAsyncText('B');
@@ -2022,7 +1995,6 @@ describe('ReactSuspenseList', () => {
1995 );
1996 });
1997
2025 - // @gate experimental
1998 it('eventually resolves a nested forwards suspense list', async () => {
1999 const B = createAsyncText('B');
2000
@@ -2085,7 +2057,6 @@ describe('ReactSuspenseList', () => {
2057 );
2058 });
2059
2088 - // @gate experimental
2060 it('eventually resolves a nested forwards suspense list with a hidden tail', async () => {
2061 const B = createAsyncText('B');
2062
@@ -2132,7 +2103,6 @@ describe('ReactSuspenseList', () => {
2103 );
2104 });
2105
2135 - // @gate experimental
2106 it('eventually resolves two nested forwards suspense lists with a hidden tail', async () => {
2107 const B = createAsyncText('B');
2108
@@ -2200,7 +2170,6 @@ describe('ReactSuspenseList', () => {
2170 );
2171 });
2172
2203 - // @gate experimental
2173 it('can do unrelated adjacent updates', async () => {
2174 let updateAdjacent;
2175 function Adjacent() {
@@ -2247,7 +2216,6 @@ describe('ReactSuspenseList', () => {
2216 );
2217 });
2218
2250 - // @gate experimental
2219 it('is able to re-suspend the last rows during an update with hidden', async () => {
2220 const AsyncB = createAsyncText('B');
2221
@@ -2336,7 +2304,6 @@ describe('ReactSuspenseList', () => {
2304 expect(previousInst).toBe(setAsyncB);
2305 });
2306
2339 - // @gate experimental
2307 it('is able to re-suspend the last rows during an update with hidden', async () => {
2308 const AsyncB = createAsyncText('B');
2309
@@ -2425,7 +2392,6 @@ describe('ReactSuspenseList', () => {
2392 expect(previousInst).toBe(setAsyncB);
2393 });
2394
2428 - // @gate experimental
2395 it('is able to interrupt a partially rendered tree and continue later', async () => {
2396 const AsyncA = createAsyncText('A');
2397
@@ -2462,7 +2428,7 @@ describe('ReactSuspenseList', () => {
2428 await ReactNoop.act(async () => {
2429 // Add a few items at the end.
2430 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2465 - React.unstable_startTransition(() => {
2431 + React.startTransition(() => {
2432 updateLowPri(true);
2433 });
2434 } else {
@@ -2504,7 +2470,6 @@ describe('ReactSuspenseList', () => {
2470 );
2471 });
2472
2507 - // @gate experimental
2473 it('can resume class components when revealed together', async () => {
2474 const A = createAsyncText('A');
2475 const B = createAsyncText('B');
@@ -2567,7 +2532,6 @@ describe('ReactSuspenseList', () => {
2532 );
2533 });
2534
2570 - // @gate experimental
2535 it('should be able to progressively show CPU expensive rows with two pass rendering', async () => {
2536 function TwoPass({text}) {
2537 const [pass, setPass] = React.useState(0);
@@ -2605,7 +2569,7 @@ describe('ReactSuspenseList', () => {
2569 }
2570
2571 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2608 - React.unstable_startTransition(() => {
2572 + React.startTransition(() => {
2573 ReactNoop.render(<App />);
2574 });
2575 } else {
@@ -2638,7 +2602,6 @@ describe('ReactSuspenseList', () => {
2602 );
2603 });
2604
2641 - // @gate experimental
2605 it('should be able to progressively show rows with two pass rendering and visible', async () => {
2606 function TwoPass({text}) {
2607 const [pass, setPass] = React.useState(0);
@@ -2678,7 +2641,7 @@ describe('ReactSuspenseList', () => {
2641 }
2642
2643 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2681 - React.unstable_startTransition(() => {
2644 + React.startTransition(() => {
2645 ReactNoop.render(<App />);
2646 });
2647 } else {
@@ -2720,7 +2683,7 @@ describe('ReactSuspenseList', () => {
2683 );
2684 });
2685
2723 - // @gate experimental && enableProfilerTimer
2686 + // @gate enableProfilerTimer
2687 it('counts the actual duration when profiling a SuspenseList', async () => {
2688 // Order of parameters: id, phase, actualDuration, treeBaseDuration
2689 const onRender = jest.fn();
packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.js
+44 -61
@@ -212,7 +212,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
212 }
213
214 if (gate(flags => flags.enableSyncDefaultUpdates)) {
215 - React.unstable_startTransition(() => {
215 + React.startTransition(() => {
216 ReactNoop.render(<Foo />);
217 });
218 } else {
@@ -284,7 +284,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
284
285 // The update will suspend.
286 if (gate(flags => flags.enableSyncDefaultUpdates)) {
287 - React.unstable_startTransition(() => {
287 + React.startTransition(() => {
288 ReactNoop.render(<Foo renderBar={true} />);
289 });
290 } else {
@@ -354,7 +354,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
354 expect(Scheduler).toFlushAndYield([]);
355 // B suspends. Continue rendering the remaining siblings.
356 if (gate(flags => flags.enableSyncDefaultUpdates)) {
357 - React.unstable_startTransition(() => {
357 + React.startTransition(() => {
358 ReactNoop.render(
359 <Suspense fallback={<Text text="Loading..." />}>
360 <Text text="A" />
@@ -401,7 +401,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
401 // TODO: Delete this feature flag.
402 // @gate !replayFailedUnitOfWorkWithInvokeGuardedCallback || !__DEV__
403 // @gate enableCache
404 - // @gate experimental || !enableSyncDefaultUpdates
404 it('retries on error', async () => {
405 class ErrorBoundary extends React.Component {
406 state = {error: null};
@@ -437,7 +436,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
436 expect(ReactNoop.getChildren()).toEqual([]);
437
438 if (gate(flags => flags.enableSyncDefaultUpdates)) {
440 - React.unstable_startTransition(() => {
439 + React.startTransition(() => {
440 ReactNoop.render(<App renderContent={true} />);
441 });
442 } else {
@@ -567,7 +566,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
566 });
567
568 // @gate enableCache
570 - // @gate experimental || !enableSyncDefaultUpdates
569 it('keeps working on lower priority work after being pinged', async () => {
570 // Advance the virtual time so that we're close to the edge of a bucket.
571 ReactNoop.expire(149);
@@ -586,7 +584,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
584 expect(ReactNoop.getChildren()).toEqual([]);
585
586 if (gate(flags => flags.enableSyncDefaultUpdates)) {
589 - React.unstable_startTransition(() => {
587 + React.startTransition(() => {
588 ReactNoop.render(<App showA={true} showB={false} />);
589 });
590 } else {
@@ -599,7 +597,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
597 // but not enough to expire the suspense timeout.
598 ReactNoop.expire(120);
599 if (gate(flags => flags.enableSyncDefaultUpdates)) {
602 - React.unstable_startTransition(() => {
600 + React.startTransition(() => {
601 ReactNoop.render(<App showA={true} showB={true} />);
602 });
603 } else {
@@ -630,7 +628,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
628 // Default pri
629 ReactNoop.render(<App />);
630 // Low pri
633 - React.unstable_startTransition(() => {
631 + React.startTransition(() => {
632 ReactNoop.render(<App hide={true} />);
633 });
634
@@ -647,7 +645,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
645 // times model. Might not make sense in the new model.
646 // TODO: This test doesn't over what it was originally designed to test.
647 // Either rewrite or delete.
650 - // @gate experimental || !enableSyncDefaultUpdates
648 it('tries each subsequent level after suspending', async () => {
649 const root = ReactNoop.createRoot();
650
@@ -683,7 +680,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
680 // Schedule an update at several distinct expiration times
681 await ReactNoop.act(async () => {
682 if (gate(flags => flags.enableSyncDefaultUpdates)) {
686 - React.unstable_startTransition(() => {
683 + React.startTransition(() => {
684 root.render(<App step={1} shouldSuspend={true} />);
685 });
686 } else {
@@ -694,7 +691,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
691 interrupt();
692
693 if (gate(flags => flags.enableSyncDefaultUpdates)) {
697 - React.unstable_startTransition(() => {
694 + React.startTransition(() => {
695 root.render(<App step={2} shouldSuspend={true} />);
696 });
697 } else {
@@ -705,7 +702,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
702 interrupt();
703
704 if (gate(flags => flags.enableSyncDefaultUpdates)) {
708 - React.unstable_startTransition(() => {
705 + React.startTransition(() => {
706 root.render(<App step={3} shouldSuspend={true} />);
707 });
708 } else {
@@ -928,7 +925,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
925 expect(ReactNoop.getChildren()).toEqual([span('Async'), span('Sync')]);
926 });
927
931 - // @gate experimental
928 + // @gate enableCache
929 it('does not expire for transitions', async () => {
930 ReactNoop.render(
931 <Fragment>
@@ -937,7 +934,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
934 );
935 expect(Scheduler).toFlushAndYield([]);
936
940 - React.unstable_startTransition(() => {
937 + React.startTransition(() => {
938 ReactNoop.render(
939 <Fragment>
940 <Suspense fallback={<Text text="Loading..." />}>
@@ -984,7 +981,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
981 expect(Scheduler).toFlushAndYield([]);
982 expect(ReactNoop.getChildren()).toEqual([]);
983 if (gate(flags => flags.enableSyncDefaultUpdates)) {
987 - React.unstable_startTransition(() => {
984 + React.startTransition(() => {
985 ReactNoop.render(
986 <>
987 <Suspense fallback={<Text text="Loading..." />}>
@@ -1051,7 +1048,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1048 expect(Scheduler).toFlushAndYield([]);
1049
1050 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1054 - React.unstable_startTransition(() => {
1051 + React.startTransition(() => {
1052 ReactNoop.render(
1053 <Suspense fallback={<Text text="Loading..." />}>
1054 <AsyncText text="Async" />
@@ -1075,7 +1072,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1072 expect(ReactNoop.getChildren()).toEqual([span('Async')]);
1073 });
1074
1078 - // @gate experimental
1075 // @gate enableCache
1076 it('starts working on an update even if its priority falls between two suspended levels', async () => {
1077 function App(props) {
@@ -1096,7 +1092,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1092 expect(Scheduler).toFlushAndYield(['S']);
1093
1094 // Schedule an update, and suspend for up to 5 seconds.
1099 - React.unstable_startTransition(() => ReactNoop.render(<App text="A" />));
1095 + React.startTransition(() => ReactNoop.render(<App text="A" />));
1096 // The update should suspend.
1097 expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
1098 expect(ReactNoop.getChildren()).toEqual([span('S')]);
@@ -1108,7 +1104,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1104 expect(ReactNoop.getChildren()).toEqual([span('S')]);
1105
1106 // Schedule another low priority update.
1111 - React.unstable_startTransition(() => ReactNoop.render(<App text="B" />));
1107 + React.startTransition(() => ReactNoop.render(<App text="B" />));
1108 // This update should also suspend.
1109 expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
1110 expect(ReactNoop.getChildren()).toEqual([span('S')]);
@@ -1857,7 +1853,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1853 });
1854
1855 // @gate enableCache
1860 - // @gate experimental || !enableSyncDefaultUpdates
1856 it('suspends for longer if something took a long (CPU bound) time to render', async () => {
1857 function Foo({renderContent}) {
1858 Scheduler.unstable_yieldValue('Foo');
@@ -1872,7 +1867,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
1867 expect(Scheduler).toFlushAndYield(['Foo']);
1868
1869 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1875 - React.unstable_startTransition(() => {
1870 + React.startTransition(() => {
1871 ReactNoop.render(<Foo renderContent={true} />);
1872 });
1873 } else {
@@ -2044,7 +2039,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2039 expect(Scheduler).toFlushAndYield(['Foo']);
2040
2041 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2047 - React.unstable_startTransition(() => {
2042 + React.startTransition(() => {
2043 ReactNoop.render(<Foo renderContent={true} />);
2044 });
2045 } else {
@@ -2365,7 +2360,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2360 expect(ReactNoop.getChildren()).toEqual([span('A')]);
2361
2362 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2368 - React.unstable_startTransition(() => {
2363 + React.startTransition(() => {
2364 ReactNoop.render(<Foo showB={true} />);
2365 });
2366 } else {
@@ -2445,7 +2440,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2440 });
2441
2442 describe('startTransition', () => {
2448 - // @gate experimental
2443 // @gate enableCache
2444 it('top level render', async () => {
2445 function App({page}) {
@@ -2457,7 +2451,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2451 }
2452
2453 // Initial render.
2460 - React.unstable_startTransition(() => ReactNoop.render(<App page="A" />));
2454 + React.startTransition(() => ReactNoop.render(<App page="A" />));
2455
2456 expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
2457 // Only a short time is needed to unsuspend the initial loading state.
@@ -2471,7 +2465,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2465 expect(ReactNoop.getChildren()).toEqual([span('A')]);
2466
2467 // Start transition.
2474 - React.unstable_startTransition(() => ReactNoop.render(<App page="B" />));
2468 + React.startTransition(() => ReactNoop.render(<App page="B" />));
2469
2470 expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
2471 Scheduler.unstable_advanceTime(100000);
@@ -2485,7 +2479,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2479 expect(ReactNoop.getChildren()).toEqual([span('B')]);
2480 });
2481
2488 - // @gate experimental
2482 // @gate enableCache
2483 it('hooks', async () => {
2484 let transitionToPage;
@@ -2507,7 +2500,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2500
2501 // Initial render.
2502 await ReactNoop.act(async () => {
2510 - React.unstable_startTransition(() => transitionToPage('A'));
2503 + React.startTransition(() => transitionToPage('A'));
2504
2505 expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
2506 // Only a short time is needed to unsuspend the initial loading state.
@@ -2523,7 +2516,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2516
2517 // Start transition.
2518 await ReactNoop.act(async () => {
2526 - React.unstable_startTransition(() => transitionToPage('B'));
2519 + React.startTransition(() => transitionToPage('B'));
2520
2521 expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
2522 Scheduler.unstable_advanceTime(100000);
@@ -2538,7 +2531,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2531 expect(ReactNoop.getChildren()).toEqual([span('B')]);
2532 });
2533
2541 - // @gate experimental
2534 // @gate enableCache
2535 it('classes', async () => {
2536 let transitionToPage;
@@ -2563,7 +2555,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2555
2556 // Initial render.
2557 await ReactNoop.act(async () => {
2566 - React.unstable_startTransition(() => transitionToPage('A'));
2558 + React.startTransition(() => transitionToPage('A'));
2559
2560 expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
2561 // Only a short time is needed to unsuspend the initial loading state.
@@ -2579,7 +2571,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2571
2572 // Start transition.
2573 await ReactNoop.act(async () => {
2582 - React.unstable_startTransition(() => transitionToPage('B'));
2574 + React.startTransition(() => transitionToPage('B'));
2575
2576 expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
2577 Scheduler.unstable_advanceTime(100000);
@@ -2596,7 +2588,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2588 });
2589
2590 describe('delays transitions when using React.startTranistion', () => {
2599 - // @gate experimental
2591 // @gate enableCache
2592 it('top level render', async () => {
2593 function App({page}) {
@@ -2608,7 +2599,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2599 }
2600
2601 // Initial render.
2611 - React.unstable_startTransition(() => ReactNoop.render(<App page="A" />));
2602 + React.startTransition(() => ReactNoop.render(<App page="A" />));
2603
2604 expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
2605 // Only a short time is needed to unsuspend the initial loading state.
@@ -2622,7 +2613,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2613 expect(ReactNoop.getChildren()).toEqual([span('A')]);
2614
2615 // Start transition.
2625 - React.unstable_startTransition(() => ReactNoop.render(<App page="B" />));
2616 + React.startTransition(() => ReactNoop.render(<App page="B" />));
2617
2618 expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
2619 Scheduler.unstable_advanceTime(2999);
@@ -2637,7 +2628,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2628 expect(ReactNoop.getChildren()).toEqual([span('B')]);
2629
2630 // Start a long (infinite) transition.
2640 - React.unstable_startTransition(() => ReactNoop.render(<App page="C" />));
2631 + React.startTransition(() => ReactNoop.render(<App page="C" />));
2632 expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
2633
2634 // Even after lots of time has passed, we have still not yet flushed the
@@ -2647,7 +2638,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2638 expect(ReactNoop.getChildren()).toEqual([span('B')]);
2639 });
2640
2650 - // @gate experimental
2641 // @gate enableCache
2642 it('hooks', async () => {
2643 let transitionToPage;
@@ -2669,7 +2659,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2659
2660 // Initial render.
2661 await ReactNoop.act(async () => {
2672 - React.unstable_startTransition(() => transitionToPage('A'));
2662 + React.startTransition(() => transitionToPage('A'));
2663
2664 expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
2665 // Only a short time is needed to unsuspend the initial loading state.
@@ -2685,7 +2675,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2675
2676 // Start transition.
2677 await ReactNoop.act(async () => {
2688 - React.unstable_startTransition(() => transitionToPage('B'));
2678 + React.startTransition(() => transitionToPage('B'));
2679
2680 expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
2681
@@ -2703,7 +2693,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2693
2694 // Start a long (infinite) transition.
2695 await ReactNoop.act(async () => {
2706 - React.unstable_startTransition(() => transitionToPage('C'));
2696 + React.startTransition(() => transitionToPage('C'));
2697
2698 expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
2699
@@ -2715,7 +2705,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2705 });
2706 });
2707
2718 - // @gate experimental
2708 // @gate enableCache
2709 it('classes', async () => {
2710 let transitionToPage;
@@ -2740,7 +2729,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2729
2730 // Initial render.
2731 await ReactNoop.act(async () => {
2743 - React.unstable_startTransition(() => transitionToPage('A'));
2732 + React.startTransition(() => transitionToPage('A'));
2733
2734 expect(Scheduler).toFlushAndYield(['Suspend! [A]', 'Loading...']);
2735 // Only a short time is needed to unsuspend the initial loading state.
@@ -2756,7 +2745,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2745
2746 // Start transition.
2747 await ReactNoop.act(async () => {
2759 - React.unstable_startTransition(() => transitionToPage('B'));
2748 + React.startTransition(() => transitionToPage('B'));
2749
2750 expect(Scheduler).toFlushAndYield(['Suspend! [B]', 'Loading...']);
2751 Scheduler.unstable_advanceTime(2999);
@@ -2773,7 +2762,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2762
2763 // Start a long (infinite) transition.
2764 await ReactNoop.act(async () => {
2776 - React.unstable_startTransition(() => transitionToPage('C'));
2765 + React.startTransition(() => transitionToPage('C'));
2766
2767 expect(Scheduler).toFlushAndYield(['Suspend! [C]', 'Loading...']);
2768
@@ -2786,7 +2775,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2775 });
2776 });
2777
2789 - // @gate experimental
2778 // @gate enableCache
2779 it('do not show placeholder when updating an avoided boundary with startTransition', async () => {
2780 function App({page}) {
@@ -2810,7 +2798,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2798 expect(ReactNoop.getChildren()).toEqual([span('Hi!'), span('A')]);
2799
2800 // Start transition.
2813 - React.unstable_startTransition(() => ReactNoop.render(<App page="B" />));
2801 + React.startTransition(() => ReactNoop.render(<App page="B" />));
2802
2803 expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']);
2804
@@ -2831,7 +2819,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2819 );
2820 });
2821
2834 - // @gate experimental
2822 // @gate enableCache
2823 it('do not show placeholder when mounting an avoided boundary with startTransition', async () => {
2824 function App({page}) {
@@ -2857,7 +2844,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2844 expect(ReactNoop.getChildren()).toEqual([span('Hi!'), span('A')]);
2845
2846 // Start transition.
2860 - React.unstable_startTransition(() => ReactNoop.render(<App page="B" />));
2847 + React.startTransition(() => ReactNoop.render(<App page="B" />));
2848
2849 expect(Scheduler).toFlushAndYield(['Hi!', 'Suspend! [B]', 'Loading B...']);
2850
@@ -2913,7 +2900,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2900 // Update. Since showing a fallback would hide content that's already
2901 // visible, it should suspend for a JND without committing.
2902 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2916 - React.unstable_startTransition(() => {
2903 + React.startTransition(() => {
2904 root.render(<App text="First update" />);
2905 });
2906 } else {
@@ -2926,7 +2913,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2913
2914 // Update again. This should also suspend for a JND.
2915 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2929 - React.unstable_startTransition(() => {
2916 + React.startTransition(() => {
2917 root.render(<App text="Second update" />);
2918 });
2919 } else {
@@ -2992,7 +2979,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
2979 expect(root).toMatchRenderedOutput(<span prop="Foo" />);
2980 });
2981
2995 - // @gate experimental
2982 // @gate enableCache
2983 it('should not render hidden content while suspended on higher pri', async () => {
2984 function Offscreen() {
@@ -3021,7 +3007,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3007 expect(ReactNoop).toMatchRenderedOutput(<div hidden={true} />);
3008
3009 // Start transition.
3024 - React.unstable_startTransition(() => {
3010 + React.startTransition(() => {
3011 ReactNoop.render(<App showContent={true} />);
3012 });
3013
@@ -3043,7 +3029,6 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3029 );
3030 });
3031
3046 - // @gate experimental
3032 // @gate enableCache
3033 it('should be able to unblock higher pri content before suspended hidden', async () => {
3034 function Offscreen() {
@@ -3074,7 +3059,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3059 expect(Scheduler).toFlushAndYieldThrough(['Suspend! [A]']);
3060
3061 // Start transition.
3077 - React.unstable_startTransition(() => {
3062 + React.startTransition(() => {
3063 ReactNoop.render(<App showContent={true} />);
3064 });
3065
@@ -3272,7 +3257,7 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3257 // update even though the primary tree is suspended.
3258 await ReactNoop.act(async () => {
3259 setAppText('C');
3275 - React.unstable_startTransition(() => {
3260 + React.startTransition(() => {
3261 setFallbackText('Still loading...');
3262 });
3263 });
@@ -3705,11 +3690,10 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3690 );
3691 });
3692
3708 - // @gate experimental
3693 // @gate enableCache
3694 // @gate !enableSyncDefaultUpdates
3695 it('regression: ping at high priority causes update to be dropped', async () => {
3712 - const {useState, unstable_useTransition: useTransition} = React;
3696 + const {useState, useTransition} = React;
3697
3698 let setTextA;
3699 function A() {
@@ -3818,15 +3802,14 @@ describe('ReactSuspenseWithNoopRenderer', () => {
3802 });
3803
3804 // Regression: https://github.com/facebook/react/issues/18486
3821 - // @gate experimental
3805 // @gate enableCache
3806 it('does not get stuck in pending state with render phase updates', async () => {
3807 let setTextWithShortTransition;
3808 let setTextWithLongTransition;
3809
3810 function App() {
3828 - const [isPending1, startShortTransition] = React.unstable_useTransition();
3829 - const [isPending2, startLongTransition] = React.unstable_useTransition();
3811 + const [isPending1, startShortTransition] = React.useTransition();
3812 + const [isPending2, startLongTransition] = React.useTransition();
3813 const isPending = isPending1 || isPending2;
3814 const [text, setText] = React.useState('');
3815 const [mirror, setMirror] = React.useState('');
packages/react-reconciler/src/__tests__/ReactTransition-test.js
+3 -15
@@ -32,9 +32,9 @@ describe('ReactTransition', () => {
32 Scheduler = require('scheduler');
33 useState = React.useState;
34 useLayoutEffect = React.useLayoutEffect;
35 - useTransition = React.unstable_useTransition;
35 + useTransition = React.useTransition;
36 Suspense = React.Suspense;
37 - startTransition = React.unstable_startTransition;
37 + startTransition = React.startTransition;
38 getCacheForType = React.unstable_getCacheForType;
39 act = ReactNoop.act;
40
@@ -158,7 +158,6 @@ describe('ReactTransition', () => {
158 }
159 }
160
161 - // @gate experimental
161 // @gate enableCache
162 test('isPending works even if called from outside an input event', async () => {
163 let start;
@@ -200,7 +199,6 @@ describe('ReactTransition', () => {
199 expect(root).toMatchRenderedOutput('Async');
200 });
201
203 - // @gate experimental
202 // @gate enableCache
203 test(
204 'when multiple transitions update the same queue, only the most recent ' +
@@ -320,7 +318,6 @@ describe('ReactTransition', () => {
318 );
319
320 // Same as previous test, but for class update queue.
323 - // @gate experimental
321 // @gate enableCache
322 test(
323 'when multiple transitions update the same queue, only the most recent ' +
@@ -445,7 +442,6 @@ describe('ReactTransition', () => {
442 },
443 );
444
448 - // @gate experimental
445 // @gate enableCache
446 test(
447 'when multiple transitions update overlapping queues, all the transitions ' +
@@ -551,7 +547,6 @@ describe('ReactTransition', () => {
547 },
548 );
549
554 - // @gate experimental
550 // @gate enableCache
551 test('interrupt a refresh transition if a new transition is scheduled', async () => {
552 const root = ReactNoop.createRoot();
@@ -607,7 +602,6 @@ describe('ReactTransition', () => {
602 expect(root).toMatchRenderedOutput('Updated');
603 });
604
610 - // @gate experimental
605 // @gate enableCache
606 test(
607 "interrupt a refresh transition when something suspends and we've " +
@@ -669,7 +663,7 @@ describe('ReactTransition', () => {
663 expect(Scheduler).toFlushAndYieldThrough(['A']);
664
665 // Now schedule a second transition. We won't interrupt the first one.
672 - React.unstable_startTransition(() => {
666 + React.startTransition(() => {
667 setShouldHideInParent(true);
668 });
669 // Continue rendering the first transition.
@@ -710,7 +704,6 @@ describe('ReactTransition', () => {
704 },
705 );
706
713 - // @gate experimental
707 // @gate enableCache
708 test(
709 'interrupt a refresh transition when something suspends and a parent ' +
@@ -776,8 +769,6 @@ describe('ReactTransition', () => {
769 },
770 );
771
779 - // @gate experimental
780 - // @gate enableCache
772 it('should render normal pri updates scheduled after transitions before transitions', async () => {
773 let updateTransitionPri;
774 let updateNormalPri;
@@ -833,7 +824,6 @@ describe('ReactTransition', () => {
824 expect(root).toMatchRenderedOutput('Transition pri: 1, Normal pri: 1');
825 });
826
836 - // @gate experimental
827 // @gate enableCache
828 it('should render normal pri updates before transition suspense retries', async () => {
829 let updateTransitionPri;
@@ -898,8 +888,6 @@ describe('ReactTransition', () => {
888 expect(root).toMatchRenderedOutput('Async, Normal pri: 1');
889 });
890
901 - // @gate experimental
902 - // @gate enableCache
891 it('should not interrupt transitions with normal pri updates', async () => {
892 let updateNormalPri;
893 let updateTransitionPri;
packages/react-reconciler/src/__tests__/ReactUpdatePriority-test.js
+1 -2
@@ -15,7 +15,7 @@ describe('ReactUpdatePriority', () => {
15 Scheduler = require('scheduler');
16 ContinuousEventPriority = require('react-reconciler/constants')
17 .ContinuousEventPriority;
18 - startTransition = React.unstable_startTransition;
18 + startTransition = React.startTransition;
19 useState = React.useState;
20 useEffect = React.useEffect;
21 });
@@ -84,7 +84,6 @@ describe('ReactUpdatePriority', () => {
84 expect(Scheduler).toHaveYielded(['Idle: 2, Default: 2']);
85 });
86
87 - // @gate experimental
87 test('continuous updates should interrupt transisions', async () => {
88 const root = ReactNoop.createRoot();
89
packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js
+4 -7
@@ -153,7 +153,6 @@ describe('updaters', () => {
153 expect(allSchedulerTypes).toEqual([[null], [SchedulingComponent]]);
154 });
155
156 - // @gate experimental
156 it('should cover cascading updates', async () => {
157 let triggerActiveCascade = null;
158 let triggerPassiveCascade = null;
@@ -183,7 +182,7 @@ describe('updaters', () => {
182 return count;
183 };
184
186 - const root = ReactDOM.unstable_createRoot(document.createElement('div'));
185 + const root = ReactDOM.createRoot(document.createElement('div'));
186 await ReactTestUtils.act(async () => {
187 root.render(<Parent />);
188 expect(Scheduler).toFlushAndYieldThrough([
@@ -292,7 +291,6 @@ describe('updaters', () => {
291 done();
292 });
293
295 - // @gate experimental
294 it('should cover error handling', async () => {
295 let triggerError = null;
296
@@ -329,7 +327,7 @@ describe('updaters', () => {
327 throw new Error('Hello');
328 };
329
332 - const root = ReactDOM.unstable_createRoot(document.createElement('div'));
330 + const root = ReactDOM.createRoot(document.createElement('div'));
331 await ReactTestUtils.act(async () => {
332 root.render(<Parent shouldError={false} />);
333 });
@@ -349,7 +347,6 @@ describe('updaters', () => {
347 Scheduler.unstable_flushAll();
348 });
349
352 - // @gate experimental
350 it('should distinguish between updaters in the case of interleaved work', async () => {
351 const {
352 FunctionComponent,
@@ -368,7 +365,7 @@ describe('updaters', () => {
365 const LowPriorityUpdater = () => {
366 const [count, setCount] = React.useState(0);
367 triggerLowPriorityUpdate = () => {
371 - React.unstable_startTransition(() => {
368 + React.startTransition(() => {
369 setCount(prevCount => prevCount + 1);
370 });
371 };
@@ -380,7 +377,7 @@ describe('updaters', () => {
377 return null;
378 };
379
383 - const root = ReactDOM.unstable_createRoot(document.createElement('div'));
380 + const root = ReactDOM.createRoot(document.createElement('div'));
381 root.render(
382 <React.Fragment>
383 <SyncPriorityUpdater />
packages/react-reconciler/src/__tests__/SchedulingProfiler-test.internal.js
+1 -2
@@ -149,7 +149,6 @@ describe('SchedulingProfiler', () => {
149 });
150
151 // @gate enableSchedulingProfiler
152 - // @gate experimental || !enableSyncDefaultUpdates
152 it('should mark render yields', async () => {
153 function Bar() {
154 Scheduler.unstable_yieldValue('Bar');
@@ -162,7 +161,7 @@ describe('SchedulingProfiler', () => {
161 }
162
163 if (gate(flags => flags.enableSyncDefaultUpdates)) {
165 - React.unstable_startTransition(() => {
164 + React.startTransition(() => {
165 ReactNoop.render(<Foo />);
166 });
167
packages/react-reconciler/src/__tests__/SchedulingProfilerLabels-test.internal.js
-3
@@ -100,7 +100,6 @@ describe('SchedulingProfiler labels', () => {
100 );
101 });
102
103 - // @gate experimental
103 // @gate enableSchedulingProfiler
104 it('regression test DefaultLane', () => {
105 const container = document.createElement('div');
@@ -114,7 +113,6 @@ describe('SchedulingProfiler labels', () => {
113 });
114 });
115
117 - // @gate experimental
116 // @gate enableSchedulingProfiler
117 // @gate !enableLegacyFBSupport
118 it('regression test InputDiscreteLane', () => {
@@ -144,7 +142,6 @@ describe('SchedulingProfiler labels', () => {
142 );
143 });
144
147 - // @gate experimental
145 // @gate enableSchedulingProfiler
146 it('regression test InputContinuousLane', () => {
147 const container = document.createElement('div');
packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js
+16 -47
@@ -31,8 +31,11 @@ function loadModules() {
31 ReactNoop = require('react-noop-renderer');
32 Scheduler = require('scheduler');
33 act = ReactNoop.act;
34 - createMutableSource = React.unstable_createMutableSource;
35 - useMutableSource = React.unstable_useMutableSource;
34 +
35 + // Stable entrypoints export with "unstable_" prefix.
36 + createMutableSource =
37 + React.createMutableSource || React.unstable_createMutableSource;
38 + useMutableSource = React.useMutableSource || React.unstable_useMutableSource;
39 }
40
41 describe('useMutableSource', () => {
@@ -138,7 +141,6 @@ describe('useMutableSource', () => {
141
142 beforeEach(loadModules);
143
141 - // @gate experimental
144 it('should subscribe to a source and schedule updates when it changes', () => {
145 const source = createSource('one');
146 const mutableSource = createMutableSource(source, param => param.version);
@@ -206,14 +208,13 @@ describe('useMutableSource', () => {
208 });
209 });
210
209 - // @gate experimental
211 it('should restart work if a new source is mutated during render', () => {
212 const source = createSource('one');
213 const mutableSource = createMutableSource(source, param => param.version);
214
215 act(() => {
216 if (gate(flags => flags.enableSyncDefaultUpdates)) {
216 - React.unstable_startTransition(() => {
217 + React.startTransition(() => {
218 ReactNoop.render(
219 <>
220 <Component
@@ -262,7 +263,6 @@ describe('useMutableSource', () => {
263 });
264 });
265
265 - // @gate experimental
266 it('should schedule an update if a new source is mutated between render and commit (subscription)', () => {
267 const source = createSource('one');
268 const mutableSource = createMutableSource(source, param => param.version);
@@ -302,7 +302,6 @@ describe('useMutableSource', () => {
302 });
303 });
304
305 - // @gate experimental
305 it('should unsubscribe and resubscribe if a new source is used', () => {
306 const sourceA = createSource('a-one');
307 const mutableSourceA = createMutableSource(
@@ -359,7 +358,6 @@ describe('useMutableSource', () => {
358 });
359 });
360
362 - // @gate experimental
361 it('should unsubscribe and resubscribe if a new subscribe function is provided', () => {
362 const source = createSource('a-one');
363 const mutableSource = createMutableSource(source, param => param.version);
@@ -424,7 +422,6 @@ describe('useMutableSource', () => {
422 });
423 });
424
427 - // @gate experimental
425 it('should re-use previously read snapshot value when reading is unsafe', () => {
426 const source = createSource('one');
427 const mutableSource = createMutableSource(source, param => param.version);
@@ -452,7 +449,7 @@ describe('useMutableSource', () => {
449 // Changing values should schedule an update with React.
450 // Start working on this update but don't finish it.
451 if (gate(flags => flags.enableSyncDefaultUpdates)) {
455 - React.unstable_startTransition(() => {
452 + React.startTransition(() => {
453 source.value = 'two';
454 });
455 } else {
@@ -487,7 +484,6 @@ describe('useMutableSource', () => {
484 });
485 });
486
490 - // @gate experimental
487 it('should read from source on newly mounted subtree if no pending updates are scheduled for source', () => {
488 const source = createSource('one');
489 const mutableSource = createMutableSource(source, param => param.version);
@@ -527,7 +523,6 @@ describe('useMutableSource', () => {
523 });
524 });
525
530 - // @gate experimental
526 it('should throw and restart render if source and snapshot are unavailable during an update', () => {
527 const source = createSource('one');
528 const mutableSource = createMutableSource(source, param => param.version);
@@ -591,7 +586,6 @@ describe('useMutableSource', () => {
586 });
587 });
588
594 - // @gate experimental
589 it('should throw and restart render if source and snapshot are unavailable during a sync update', () => {
590 const source = createSource('one');
591 const mutableSource = createMutableSource(source, param => param.version);
@@ -655,7 +649,6 @@ describe('useMutableSource', () => {
649 });
650 });
651
658 - // @gate experimental
652 it('should only update components whose subscriptions fire', () => {
653 const source = createComplexSource('a:one', 'b:one');
654 const mutableSource = createMutableSource(source, param => param.version);
@@ -694,7 +687,6 @@ describe('useMutableSource', () => {
687 });
688 });
689
697 - // @gate experimental
690 it('should detect tearing in part of the store not yet subscribed to', () => {
691 const source = createComplexSource('a:one', 'b:one');
692 const mutableSource = createMutableSource(source, param => param.version);
@@ -722,7 +714,7 @@ describe('useMutableSource', () => {
714 // Because the store has not changed yet, there are no pending updates,
715 // so it is considered safe to read from when we start this render.
716 if (gate(flags => flags.enableSyncDefaultUpdates)) {
725 - React.unstable_startTransition(() => {
717 + React.startTransition(() => {
718 ReactNoop.render(
719 <>
720 <Component
@@ -787,7 +779,6 @@ describe('useMutableSource', () => {
779 });
780 });
781
790 - // @gate experimental
782 it('does not schedule an update for subscriptions that fire with an unchanged snapshot', () => {
783 const MockComponent = jest.fn(Component);
784
@@ -814,7 +805,6 @@ describe('useMutableSource', () => {
805 });
806 });
807
817 - // @gate experimental
808 it('should throw and restart if getSnapshot changes between scheduled update and re-render', () => {
809 const source = createSource('one');
810 const mutableSource = createMutableSource(source, param => param.version);
@@ -855,7 +845,6 @@ describe('useMutableSource', () => {
845 });
846 });
847
858 - // @gate experimental
848 it('should recover from a mutation during yield when other work is scheduled', () => {
849 const source = createSource('one');
850 const mutableSource = createMutableSource(source, param => param.version);
@@ -863,7 +852,7 @@ describe('useMutableSource', () => {
852 act(() => {
853 // Start a render that uses the mutable source.
854 if (gate(flags => flags.enableSyncDefaultUpdates)) {
866 - React.unstable_startTransition(() => {
855 + React.startTransition(() => {
856 ReactNoop.render(
857 <>
858 <Component
@@ -910,7 +899,6 @@ describe('useMutableSource', () => {
899 });
900 });
901
913 - // @gate experimental
902 it('should not throw if the new getSnapshot returns the same snapshot value', () => {
903 const source = createSource('one');
904 const mutableSource = createMutableSource(source, param => param.version);
@@ -965,7 +953,6 @@ describe('useMutableSource', () => {
953 });
954 });
955
968 - // @gate experimental
956 it('should not throw if getSnapshot changes but the source can be safely read from anyway', () => {
957 const source = createSource('one');
958 const mutableSource = createMutableSource(source, param => param.version);
@@ -1005,7 +992,6 @@ describe('useMutableSource', () => {
992 });
993 });
994
1008 - // @gate experimental
995 it('should still schedule an update if an eager selector throws after a mutation', () => {
996 const source = createSource({
997 friends: [
@@ -1072,7 +1058,6 @@ describe('useMutableSource', () => {
1058 });
1059 });
1060
1075 - // @gate experimental
1061 it('should not warn about updates that fire between unmount and passive unsubscribe', () => {
1062 const source = createSource('one');
1063 const mutableSource = createMutableSource(source, param => param.version);
@@ -1109,7 +1094,6 @@ describe('useMutableSource', () => {
1094 });
1095 });
1096
1112 - // @gate experimental
1097 it('should support inline selectors and updates that are processed after selector change', async () => {
1098 const source = createSource({
1099 a: 'initial',
@@ -1154,7 +1138,6 @@ describe('useMutableSource', () => {
1138 expect(root).toMatchRenderedOutput('Another update');
1139 });
1140
1157 - // @gate experimental
1141 it('should clear the update queue when getSnapshot changes with pending lower priority updates', async () => {
1142 const source = createSource({
1143 a: 'initial',
@@ -1211,7 +1194,6 @@ describe('useMutableSource', () => {
1194 expect(root).toMatchRenderedOutput('B: Update');
1195 });
1196
1214 - // @gate experimental
1197 it('should clear the update queue when source changes with pending lower priority updates', async () => {
1198 const sourceA = createSource('initial');
1199 const sourceB = createSource('initial');
@@ -1256,7 +1238,6 @@ describe('useMutableSource', () => {
1238 expect(root).toMatchRenderedOutput('B: Update');
1239 });
1240
1259 - // @gate experimental
1241 it('should always treat reading as potentially unsafe when getSnapshot changes between renders', async () => {
1242 const source = createSource({
1243 a: 'foo',
@@ -1346,7 +1327,6 @@ describe('useMutableSource', () => {
1327 expect(Scheduler).toHaveYielded(['x: bar, y: bar']);
1328 });
1329
1349 - // @gate experimental
1330 it('getSnapshot changes and then source is mutated in between paint and passive effect phase', async () => {
1331 const source = createSource({
1332 a: 'foo',
@@ -1405,7 +1385,6 @@ describe('useMutableSource', () => {
1385 expect(root).toMatchRenderedOutput('baz');
1386 });
1387
1408 - // @gate experimental
1388 it('getSnapshot changes and then source is mutated in between paint and passive effect phase, case 2', async () => {
1389 const source = createSource({
1390 a: 'a0',
@@ -1476,7 +1455,6 @@ describe('useMutableSource', () => {
1455 expect(root.getChildrenAsJSX()).toEqual('first: a1, second: a1');
1456 });
1457
1479 - // @gate experimental
1458 it(
1459 'if source is mutated after initial read but before subscription is set ' +
1460 'up, should still entangle all pending mutations even if snapshot of ' +
@@ -1533,7 +1511,7 @@ describe('useMutableSource', () => {
1511
1512 await act(async () => {
1513 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1536 - React.unstable_startTransition(() => {
1514 + React.startTransition(() => {
1515 root.render(
1516 <>
1517 <Read getSnapshot={getSnapshotA} />
@@ -1563,7 +1541,7 @@ describe('useMutableSource', () => {
1541 // read during render will happen to match the latest value. But it should
1542 // still entangle the updates to prevent the previous update (a1) from
1543 // rendering by itself.
1566 - React.unstable_startTransition(() => {
1544 + React.startTransition(() => {
1545 mutateA('a0');
1546 mutateB('b0');
1547 });
@@ -1581,7 +1559,6 @@ describe('useMutableSource', () => {
1559 },
1560 );
1561
1584 - // @gate experimental
1562 it('warns about functions being used as snapshot values', async () => {
1563 const source = createSource(() => 'a');
1564 const mutableSource = createMutableSource(source, param => param.version);
@@ -1609,7 +1586,6 @@ describe('useMutableSource', () => {
1586 expect(root).toMatchRenderedOutput('a');
1587 });
1588
1612 - // @gate experimental
1589 it('getSnapshot changes and then source is mutated during interleaved event', async () => {
1590 const {useEffect} = React;
1591
@@ -1680,7 +1656,7 @@ describe('useMutableSource', () => {
1656 await act(async () => {
1657 // Switch the parent and the child to read using the same config
1658 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1683 - React.unstable_startTransition(() => {
1659 + React.startTransition(() => {
1660 root.render(<App parentConfig={configB} childConfig={configB} />);
1661 });
1662 } else {
@@ -1692,7 +1668,7 @@ describe('useMutableSource', () => {
1668 // Mutate the config. This is at lower priority so that 1) to make sure
1669 // it doesn't happen to get batched with the in-progress render, and 2)
1670 // so it doesn't interrupt the in-progress render.
1695 - React.unstable_startTransition(() => {
1671 + React.startTransition(() => {
1672 source.valueB = '3';
1673 });
1674
@@ -1734,7 +1710,6 @@ describe('useMutableSource', () => {
1710 });
1711 });
1712
1737 - // @gate experimental
1713 it('should not tear with newly mounted component when updates were scheduled at a lower priority', async () => {
1714 const source = createSource('one');
1715 const mutableSource = createMutableSource(source, param => param.version);
@@ -1802,7 +1777,7 @@ describe('useMutableSource', () => {
1777 expect(source.listenerCount).toBe(1);
1778
1779 // Mutate -> schedule update for ComponentA
1805 - React.unstable_startTransition(() => {
1780 + React.startTransition(() => {
1781 source.value = 'two';
1782 });
1783
@@ -1815,7 +1790,6 @@ describe('useMutableSource', () => {
1790 if (__DEV__) {
1791 // See https://github.com/facebook/react/issues/19948
1792 describe('side effecte detection', () => {
1818 - // @gate experimental
1793 it('should throw if a mutable source is mutated during render', () => {
1794 const source = createSource(0);
1795 const mutableSource = createMutableSource(
@@ -1860,7 +1834,6 @@ describe('useMutableSource', () => {
1834 ]);
1835 });
1836
1863 - // @gate experimental
1837 it('should throw if a mutable source is mutated during render (legacy mode)', () => {
1838 const source = createSource('initial');
1839 const mutableSource = createMutableSource(
@@ -1899,7 +1872,6 @@ describe('useMutableSource', () => {
1872 expect(Scheduler).toHaveYielded(['MutateDuringRead:initial']);
1873 });
1874
1902 - // @gate experimental
1875 it('should not misidentify mutations after render as side effects', async () => {
1876 const source = createSource('initial');
1877 const mutableSource = createMutableSource(
@@ -1934,7 +1906,6 @@ describe('useMutableSource', () => {
1906 });
1907
1908 describe('dev warnings', () => {
1937 - // @gate experimental
1909 it('should warn if the subscribe function does not return an unsubscribe function', () => {
1910 const source = createSource('one');
1911 const mutableSource = createMutableSource(
@@ -1960,7 +1931,6 @@ describe('useMutableSource', () => {
1931 );
1932 });
1933
1963 - // @gate experimental
1934 it('should error if multiple renderers of the same type use a mutable source at the same time', () => {
1935 const source = createSource('one');
1936 const mutableSource = createMutableSource(
@@ -1971,7 +1941,7 @@ describe('useMutableSource', () => {
1941 act(() => {
1942 // Start a render that uses the mutable source.
1943 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1974 - React.unstable_startTransition(() => {
1944 + React.startTransition(() => {
1945 ReactNoop.render(
1946 <>
1947 <Component
@@ -2041,7 +2011,6 @@ describe('useMutableSource', () => {
2011 });
2012 });
2013
2044 - // @gate experimental
2014 it('should error if multiple renderers of the same type use a mutable source at the same time with mutation between', () => {
2015 const source = createSource('one');
2016 const mutableSource = createMutableSource(
@@ -2052,7 +2021,7 @@ describe('useMutableSource', () => {
2021 act(() => {
2022 // Start a render that uses the mutable source.
2023 if (gate(flags => flags.enableSyncDefaultUpdates)) {
2055 - React.unstable_startTransition(() => {
2024 + React.startTransition(() => {
2025 ReactNoop.render(
2026 <>
2027 <Component
packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js
+14 -15
@@ -27,8 +27,12 @@ describe('useMutableSourceHydration', () => {
27 Scheduler = require('scheduler');
28
29 act = require('react-dom/test-utils').unstable_concurrentAct;
30 - createMutableSource = React.unstable_createMutableSource;
31 - useMutableSource = React.unstable_useMutableSource;
30 +
31 + // Stable entrypoints export with "unstable_" prefix.
32 + createMutableSource =
33 + React.createMutableSource || React.unstable_createMutableSource;
34 + useMutableSource =
35 + React.useMutableSource || React.unstable_useMutableSource;
36 });
37
38 function dispatchAndSetCurrentEvent(el, event) {
@@ -140,7 +144,6 @@ describe('useMutableSourceHydration', () => {
144 return <div>{`${label}:${snapshot}`}</div>;
145 }
146
143 - // @gate experimental
147 it('should render and hydrate', () => {
148 const source = createSource('one');
149 const mutableSource = createMutableSource(source, param => param.version);
@@ -164,7 +167,7 @@ describe('useMutableSourceHydration', () => {
167 expect(Scheduler).toHaveYielded(['only:one']);
168 expect(source.listenerCount).toBe(0);
169
167 - const root = ReactDOM.unstable_createRoot(container, {
170 + const root = ReactDOM.createRoot(container, {
171 hydrate: true,
172 hydrationOptions: {
173 mutableSources: [mutableSource],
@@ -177,7 +180,6 @@ describe('useMutableSourceHydration', () => {
180 expect(source.listenerCount).toBe(1);
181 });
182
180 - // @gate experimental
183 it('should detect a tear before hydrating a component', () => {
184 const source = createSource('one');
185 const mutableSource = createMutableSource(source, param => param.version);
@@ -201,7 +203,7 @@ describe('useMutableSourceHydration', () => {
203 expect(Scheduler).toHaveYielded(['only:one']);
204 expect(source.listenerCount).toBe(0);
205
204 - const root = ReactDOM.unstable_createRoot(container, {
206 + const root = ReactDOM.createRoot(container, {
207 hydrate: true,
208 hydrationOptions: {
209 mutableSources: [mutableSource],
@@ -222,7 +224,6 @@ describe('useMutableSourceHydration', () => {
224 expect(source.listenerCount).toBe(1);
225 });
226
225 - // @gate experimental
227 it('should detect a tear between hydrating components', () => {
228 const source = createSource('one');
229 const mutableSource = createMutableSource(source, param => param.version);
@@ -254,7 +255,7 @@ describe('useMutableSourceHydration', () => {
255 expect(Scheduler).toHaveYielded(['a:one', 'b:one']);
256 expect(source.listenerCount).toBe(0);
257
257 - const root = ReactDOM.unstable_createRoot(container, {
258 + const root = ReactDOM.createRoot(container, {
259 hydrate: true,
260 hydrationOptions: {
261 mutableSources: [mutableSource],
@@ -263,7 +264,7 @@ describe('useMutableSourceHydration', () => {
264 expect(() => {
265 act(() => {
266 if (gate(flags => flags.enableSyncDefaultUpdates)) {
266 - React.unstable_startTransition(() => {
267 + React.startTransition(() => {
268 root.render(<TestComponent />);
269 });
270 } else {
@@ -281,7 +282,6 @@ describe('useMutableSourceHydration', () => {
282 expect(source.listenerCount).toBe(2);
283 });
284
284 - // @gate experimental
285 it('should detect a tear between hydrating components reading from different parts of a source', () => {
286 const source = createComplexSource('a:one', 'b:one');
287 const mutableSource = createMutableSource(source, param => param.version);
@@ -314,7 +314,7 @@ describe('useMutableSourceHydration', () => {
314 container.innerHTML = htmlString;
315 expect(Scheduler).toHaveYielded(['0:a:one', '1:b:one']);
316
317 - const root = ReactDOM.unstable_createRoot(container, {
317 + const root = ReactDOM.createRoot(container, {
318 hydrate: true,
319 hydrationOptions: {
320 mutableSources: [mutableSource],
@@ -323,7 +323,7 @@ describe('useMutableSourceHydration', () => {
323 expect(() => {
324 act(() => {
325 if (gate(flags => flags.enableSyncDefaultUpdates)) {
326 - React.unstable_startTransition(() => {
326 + React.startTransition(() => {
327 root.render(
328 <>
329 <Component
@@ -370,7 +370,6 @@ describe('useMutableSourceHydration', () => {
370 expect(Scheduler).toHaveYielded(['0:a:one', '1:b:two']);
371 });
372
373 - // @gate experimental
373 // @gate !enableSyncDefaultUpdates
374 it('should detect a tear during a higher priority interruption', () => {
375 const source = createSource('one');
@@ -405,7 +404,7 @@ describe('useMutableSourceHydration', () => {
404 expect(Scheduler).toHaveYielded([1, 'a:one']);
405 expect(source.listenerCount).toBe(0);
406
408 - const root = ReactDOM.unstable_createRoot(container, {
407 + const root = ReactDOM.createRoot(container, {
408 hydrate: true,
409 hydrationOptions: {
410 mutableSources: [mutableSource],
@@ -415,7 +414,7 @@ describe('useMutableSourceHydration', () => {
414 expect(() => {
415 act(() => {
416 if (gate(flags => flags.enableSyncDefaultUpdates)) {
418 - React.unstable_startTransition(() => {
417 + React.startTransition(() => {
418 root.render(<TestComponent flag={1} />);
419 });
420 } else {
packages/react-refresh/src/__tests__/ReactFresh-test.js
+1 -1
@@ -2437,7 +2437,7 @@ describe('ReactFresh', () => {
2437 };
2438 });
2439
2440 - const root = ReactDOM.unstable_createRoot(container);
2440 + const root = ReactDOM.createRoot(container);
2441 root.render(<AppV1 offscreen={true} />);
2442 expect(Scheduler).toFlushAndYieldThrough(['App#layout']);
2443 const el = container.firstChild;
packages/react-server-dom-relay/src/__tests__/ReactFlightDOMRelay-test.internal.js
-2
@@ -72,7 +72,6 @@ describe('ReactFlightDOMRelay', () => {
72 });
73 });
74
75 - // @gate experimental
75 it('can render a client component using a module reference and render there', () => {
76 function UserClient(props) {
77 return (
@@ -105,7 +104,6 @@ describe('ReactFlightDOMRelay', () => {
104 expect(container.innerHTML).toEqual('<span>Hello, Seb Smith</span>');
105 });
106
108 - // @gate experimental
107 it('can reasonably handle different element types', () => {
108 const {
109 forwardRef,
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOM-test.js
+5 -10
@@ -128,7 +128,6 @@ describe('ReactFlightDOM', () => {
128 });
129 });
130
131 - // @gate experimental
131 it('should resolve the root', async () => {
132 const {Suspense} = React;
133
@@ -171,7 +170,7 @@ describe('ReactFlightDOM', () => {
170 const response = ReactServerDOMReader.createFromReadableStream(readable);
171
172 const container = document.createElement('div');
174 - const root = ReactDOM.unstable_createRoot(container);
173 + const root = ReactDOM.createRoot(container);
174 await act(async () => {
175 root.render(<App response={response} />);
176 });
@@ -180,7 +179,6 @@ describe('ReactFlightDOM', () => {
179 );
180 });
181
183 - // @gate experimental
182 it('should not get confused by $', async () => {
183 const {Suspense} = React;
184
@@ -210,14 +208,13 @@ describe('ReactFlightDOM', () => {
208 const response = ReactServerDOMReader.createFromReadableStream(readable);
209
210 const container = document.createElement('div');
213 - const root = ReactDOM.unstable_createRoot(container);
211 + const root = ReactDOM.createRoot(container);
212 await act(async () => {
213 root.render(<App response={response} />);
214 });
215 expect(container.innerHTML).toBe('<p>$1</p>');
216 });
217
220 - // @gate experimental
218 it('should not get confused by @', async () => {
219 const {Suspense} = React;
220
@@ -247,14 +244,13 @@ describe('ReactFlightDOM', () => {
244 const response = ReactServerDOMReader.createFromReadableStream(readable);
245
246 const container = document.createElement('div');
250 - const root = ReactDOM.unstable_createRoot(container);
247 + const root = ReactDOM.createRoot(container);
248 await act(async () => {
249 root.render(<App response={response} />);
250 });
251 expect(container.innerHTML).toBe('<p>@div</p>');
252 });
253
257 - // @gate experimental
254 it('should progressively reveal server components', async () => {
255 let reportedErrors = [];
256 const {Suspense} = React;
@@ -383,7 +379,7 @@ describe('ReactFlightDOM', () => {
379 const response = ReactServerDOMReader.createFromReadableStream(readable);
380
381 const container = document.createElement('div');
386 - const root = ReactDOM.unstable_createRoot(container);
382 + const root = ReactDOM.createRoot(container);
383 await act(async () => {
384 root.render(
385 <Suspense fallback={<p>(loading)</p>}>
@@ -454,7 +450,6 @@ describe('ReactFlightDOM', () => {
450 expect(reportedErrors).toEqual([]);
451 });
452
457 - // @gate experimental
453 it('should preserve state of client components on refetch', async () => {
454 const {Suspense} = React;
455
@@ -483,7 +478,7 @@ describe('ReactFlightDOM', () => {
478 }
479
480 const container = document.createElement('div');
486 - const root = ReactDOM.unstable_createRoot(container);
481 + const root = ReactDOM.createRoot(container);
482
483 const stream1 = getTestStream();
484 ReactServerDOMWriter.pipeToNodeWritable(
packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js
+2 -4
@@ -73,7 +73,6 @@ describe('ReactTestRendererAsync', () => {
73 expect(renderer.toJSON()).toEqual(['A:2', 'B:2', 'C:2']);
74 });
75
76 - // @gate experimental || !enableSyncDefaultUpdates
76 it('flushThrough flushes until the expected values is yielded', () => {
77 function Child(props) {
78 Scheduler.unstable_yieldValue(props.children);
@@ -91,7 +90,7 @@ describe('ReactTestRendererAsync', () => {
90
91 let renderer;
92 if (gate(flags => flags.enableSyncDefaultUpdates)) {
94 - React.unstable_startTransition(() => {
93 + React.startTransition(() => {
94 renderer = ReactTestRenderer.create(<Parent step={1} />, {
95 unstable_isConcurrent: true,
96 });
@@ -112,7 +111,6 @@ describe('ReactTestRendererAsync', () => {
111 expect(renderer.toJSON()).toEqual(['A:1', 'B:1', 'C:1']);
112 });
113
115 - // @gate experimental || !enableSyncDefaultUpdates
114 it('supports high priority interruptions', () => {
115 function Child(props) {
116 Scheduler.unstable_yieldValue(props.children);
@@ -138,7 +136,7 @@ describe('ReactTestRendererAsync', () => {
136
137 let renderer;
138 if (gate(flags => flags.enableSyncDefaultUpdates)) {
141 - React.unstable_startTransition(() => {
139 + React.startTransition(() => {
140 renderer = ReactTestRenderer.create(<Example step={1} />, {
141 unstable_isConcurrent: true,
142 });
packages/react/index.classic.fb.js
+30 -33
@@ -8,55 +8,52 @@
8 */
9
10 export {
11 + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
12 Children,
12 - createRef,
13 Component,
14 + Fragment,
15 + Profiler,
16 PureComponent,
17 + StrictMode,
18 + Suspense,
19 + SuspenseList,
20 + SuspenseList as unstable_SuspenseList, // TODO: Remove once call sights updated to SuspenseList
21 + cloneElement,
22 createContext,
23 + createElement,
24 + createFactory,
25 + createMutableSource,
26 + createMutableSource as unstable_createMutableSource,
27 + createRef,
28 forwardRef,
29 + isValidElement,
30 lazy,
31 memo,
32 + startTransition,
33 + startTransition as unstable_startTransition, // TODO: Remove once call sights updated to startTransition
34 + unstable_Cache,
35 + unstable_DebugTracingMode,
36 + unstable_LegacyHidden,
37 + unstable_Scope,
38 + unstable_getCacheForType,
39 + unstable_useCacheRefresh,
40 + unstable_useOpaqueIdentifier,
41 useCallback,
42 useContext,
43 + useDebugValue,
44 + useDeferredValue,
45 + useDeferredValue as unstable_useDeferredValue, // TODO: Remove once call sights updated to useDeferredValue
46 useEffect,
47 useImperativeHandle,
23 - useDebugValue,
48 useLayoutEffect,
49 useMemo,
50 + useMutableSource,
51 + useMutableSource as unstable_useMutableSource,
52 useReducer,
53 useRef,
54 useState,
29 - useMutableSource,
30 - useMutableSource as unstable_useMutableSource,
31 - createMutableSource,
32 - createMutableSource as unstable_createMutableSource,
33 - Fragment,
34 - Profiler,
35 - StrictMode,
36 - Suspense,
37 - unstable_LegacyHidden,
38 - createElement,
39 - cloneElement,
40 - isValidElement,
41 - version,
42 - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
43 - createFactory,
44 - // exposeConcurrentModeAPIs
55 useTransition,
46 - useTransition as unstable_useTransition,
47 - useDeferredValue,
48 - useDeferredValue as unstable_useDeferredValue,
49 - startTransition,
50 - startTransition as unstable_startTransition,
51 - SuspenseList,
52 - SuspenseList as unstable_SuspenseList,
53 - unstable_getCacheForType,
54 - unstable_Cache,
55 - unstable_useCacheRefresh,
56 - // enableScopeAPI
57 - unstable_Scope,
58 - unstable_useOpaqueIdentifier,
59 - // enableDebugTracing
60 - unstable_DebugTracingMode,
56 + useTransition as unstable_useTransition, // TODO: Remove once call sights updated to useTransition
57 + version,
58 } from './src/React';
59 export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX';
packages/react/index.experimental.js
+23 -25
@@ -8,46 +8,44 @@
8 */
9
10 export {
11 + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
12 Children,
12 - createRef,
13 Component,
14 + Fragment,
15 + Profiler,
16 PureComponent,
17 + StrictMode,
18 + Suspense,
19 + SuspenseList,
20 + cloneElement,
21 createContext,
22 + createElement,
23 + createFactory,
24 + createMutableSource as unstable_createMutableSource,
25 + createRef,
26 forwardRef,
27 + isValidElement,
28 lazy,
29 memo,
30 + startTransition,
31 + unstable_Cache,
32 + unstable_DebugTracingMode,
33 + unstable_LegacyHidden,
34 + unstable_getCacheForType,
35 + unstable_useCacheRefresh,
36 + unstable_useOpaqueIdentifier,
37 useCallback,
38 useContext,
39 + useDebugValue,
40 + useDeferredValue,
41 useEffect,
42 useImperativeHandle,
23 - useDebugValue,
43 useLayoutEffect,
44 useMemo,
45 + useMutableSource as unstable_useMutableSource,
46 useReducer,
47 useRef,
48 useState,
29 - useMutableSource as unstable_useMutableSource,
30 - createMutableSource as unstable_createMutableSource,
31 - Fragment,
32 - Profiler,
33 - StrictMode,
34 - Suspense,
35 - unstable_LegacyHidden,
36 - createElement,
37 - cloneElement,
38 - isValidElement,
49 + useTransition,
50 version,
40 - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
41 - createFactory,
42 - // exposeConcurrentModeAPIs
43 - useTransition as unstable_useTransition,
44 - useDeferredValue as unstable_useDeferredValue,
45 - startTransition as unstable_startTransition,
46 - SuspenseList as unstable_SuspenseList,
47 - unstable_useOpaqueIdentifier,
48 - unstable_getCacheForType,
49 - unstable_Cache,
50 - unstable_useCacheRefresh,
51 - // enableDebugTracing
52 - unstable_DebugTracingMode,
51 } from './src/React';
packages/react/index.js
+24 -30
@@ -32,51 +32,45 @@ export type ChildrenArray<+T> = $ReadOnlyArray<ChildrenArray<T>> | T;
32 // Export all exports so that they're available in tests.
33 // We can't use export * from in Flow for some reason.
34 export {
35 + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
36 Children,
36 - createRef,
37 Component,
38 + Fragment,
39 + Profiler,
40 PureComponent,
41 + StrictMode,
42 + Suspense,
43 + SuspenseList,
44 + cloneElement,
45 createContext,
46 + createElement,
47 + createFactory,
48 + createMutableSource,
49 + createRef,
50 forwardRef,
51 + isValidElement,
52 lazy,
53 memo,
54 + startTransition,
55 + unstable_Cache,
56 + unstable_DebugTracingMode,
57 + unstable_LegacyHidden,
58 + unstable_Scope,
59 + unstable_getCacheForType,
60 + unstable_useCacheRefresh,
61 + unstable_useOpaqueIdentifier,
62 useCallback,
63 useContext,
64 + useDebugValue,
65 + useDeferredValue,
66 useEffect,
67 useImperativeHandle,
47 - useDebugValue,
68 useLayoutEffect,
69 useMemo,
70 + useMutableSource,
71 useReducer,
72 useRef,
73 useState,
53 - useMutableSource,
54 - useMutableSource as unstable_useMutableSource,
55 - createMutableSource,
56 - createMutableSource as unstable_createMutableSource,
57 - Fragment,
58 - Profiler,
59 - unstable_DebugTracingMode,
60 - StrictMode,
61 - Suspense,
62 - createElement,
63 - cloneElement,
64 - isValidElement,
65 - version,
66 - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
67 - createFactory,
74 useTransition,
69 - useTransition as unstable_useTransition,
70 - startTransition,
71 - startTransition as unstable_startTransition,
72 - useDeferredValue,
73 - useDeferredValue as unstable_useDeferredValue,
74 - SuspenseList,
75 - SuspenseList as unstable_SuspenseList,
76 - unstable_LegacyHidden,
77 - unstable_Scope,
78 - unstable_useOpaqueIdentifier,
79 - unstable_getCacheForType,
80 - unstable_Cache,
81 - unstable_useCacheRefresh,
75 + version,
76 } from './src/React';
packages/react/index.modern.fb.js
+27 -30
@@ -8,54 +8,51 @@
8 */
9
10 export {
11 + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
12 Children,
12 - createRef,
13 Component,
14 + Fragment,
15 + Profiler,
16 PureComponent,
17 + StrictMode,
18 + Suspense,
19 + SuspenseList,
20 + SuspenseList as unstable_SuspenseList, // TODO: Remove once call sights updated to SuspenseList
21 + cloneElement,
22 createContext,
23 + createElement,
24 + createMutableSource,
25 + createMutableSource as unstable_createMutableSource,
26 + createRef,
27 forwardRef,
28 + isValidElement,
29 lazy,
30 memo,
31 + startTransition,
32 + startTransition as unstable_startTransition, // TODO: Remove once call sights updated to startTransition
33 + unstable_Cache,
34 + unstable_DebugTracingMode,
35 + unstable_LegacyHidden,
36 + unstable_Scope,
37 + unstable_getCacheForType,
38 + unstable_useCacheRefresh,
39 + unstable_useOpaqueIdentifier,
40 useCallback,
41 useContext,
42 + useDebugValue,
43 + useDeferredValue,
44 + useDeferredValue as unstable_useDeferredValue, // TODO: Remove once call sights updated to useDeferredValue
45 useEffect,
46 useImperativeHandle,
23 - useDebugValue,
47 useLayoutEffect,
48 useMemo,
49 useMutableSource,
50 useMutableSource as unstable_useMutableSource,
28 - createMutableSource,
29 - createMutableSource as unstable_createMutableSource,
51 useReducer,
52 useRef,
53 useState,
33 - Fragment,
34 - Profiler,
35 - StrictMode,
36 - Suspense,
37 - unstable_LegacyHidden,
38 - createElement,
39 - cloneElement,
40 - isValidElement,
41 - version,
42 - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
43 - // exposeConcurrentModeAPIs
54 useTransition,
45 - useTransition as unstable_useTransition,
46 - useDeferredValue,
47 - useDeferredValue as unstable_useDeferredValue,
48 - startTransition,
49 - startTransition as unstable_startTransition,
50 - SuspenseList,
51 - SuspenseList as unstable_SuspenseList,
52 - unstable_getCacheForType,
53 - unstable_Cache,
54 - unstable_useCacheRefresh,
55 - // enableScopeAPI
56 - unstable_Scope,
57 - unstable_useOpaqueIdentifier,
58 - // enableDebugTracing
59 - unstable_DebugTracingMode,
55 + useTransition as unstable_useTransition, // TODO: Remove once call sights updated to useTransition
56 + version,
57 } from './src/React';
58 export {jsx, jsxs, jsxDEV} from './src/jsx/ReactJSX';
packages/react/index.stable.js
+18 -11
@@ -8,32 +8,39 @@
8 */
9
10 export {
11 + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
12 Children,
12 - createRef,
13 Component,
14 + Fragment,
15 + Profiler,
16 PureComponent,
17 + StrictMode,
18 + Suspense,
19 + SuspenseList,
20 + cloneElement,
21 createContext,
22 + createElement,
23 + createFactory,
24 + createMutableSource as unstable_createMutableSource,
25 + createRef,
26 forwardRef,
27 + isValidElement,
28 lazy,
29 memo,
30 + startTransition,
31 + unstable_useOpaqueIdentifier,
32 useCallback,
33 useContext,
34 + useDebugValue,
35 + useDeferredValue,
36 useEffect,
37 useImperativeHandle,
23 - useDebugValue,
38 useLayoutEffect,
39 useMemo,
40 + useMutableSource as unstable_useMutableSource,
41 useReducer,
42 useRef,
43 useState,
29 - Fragment,
30 - Profiler,
31 - StrictMode,
32 - Suspense,
33 - createElement,
34 - cloneElement,
35 - isValidElement,
44 + useTransition,
45 version,
37 - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
38 - createFactory,
46 } from './src/React';
packages/react/src/__tests__/ReactProfiler-test.internal.js
+7 -14
@@ -186,7 +186,6 @@ describe(`onRender`, () => {
186 expect(callback).toHaveBeenCalledTimes(2);
187 });
188
189 - // @gate experimental || !enableSyncDefaultUpdates
189 it('is not invoked until the commit phase', () => {
190 const callback = jest.fn();
191
@@ -196,7 +195,7 @@ describe(`onRender`, () => {
195 };
196
197 if (gate(flags => flags.enableSyncDefaultUpdates)) {
199 - React.unstable_startTransition(() => {
198 + React.startTransition(() => {
199 ReactTestRenderer.create(
200 <React.Profiler id="test" onRender={callback}>
201 <Yield value="first" />
@@ -690,7 +689,6 @@ describe(`onRender`, () => {
689 expect(onRender.mock.calls[2][1]).toBe('update');
690 });
691
693 - // @gate experimental
692 it('is properly distinguish updates and nested-updates when there is more than sync remaining work', () => {
693 loadModules({
694 useNoopRenderer: true,
@@ -709,7 +707,7 @@ describe(`onRender`, () => {
707 const onRender = jest.fn();
708
709 // Schedule low-priority work.
712 - React.unstable_startTransition(() =>
710 + React.startTransition(() =>
711 ReactNoop.render(
712 <React.Profiler id="root" onRender={onRender}>
713 <Component />
@@ -734,7 +732,6 @@ describe(`onRender`, () => {
732 });
733
734 describe('with regard to interruptions', () => {
737 - // @gate experimental || !enableSyncDefaultUpdates
735 it('should accumulate actual time after a scheduling interruptions', () => {
736 const callback = jest.fn();
737
@@ -748,7 +745,7 @@ describe(`onRender`, () => {
745
746 // Render partially, but run out of time before completing.
747 if (gate(flags => flags.enableSyncDefaultUpdates)) {
751 - React.unstable_startTransition(() => {
748 + React.startTransition(() => {
749 ReactTestRenderer.create(
750 <React.Profiler id="test" onRender={callback}>
751 <Yield renderTime={2} />
@@ -781,7 +778,6 @@ describe(`onRender`, () => {
778 expect(call[5]).toBe(10); // commit time
779 });
780
784 - // @gate experimental || !enableSyncDefaultUpdates
781 it('should not include time between frames', () => {
782 const callback = jest.fn();
783
@@ -796,7 +792,7 @@ describe(`onRender`, () => {
792 // Render partially, but don't finish.
793 // This partial render should take 5ms of simulated time.
794 if (gate(flags => flags.enableSyncDefaultUpdates)) {
799 - React.unstable_startTransition(() => {
795 + React.startTransition(() => {
796 ReactTestRenderer.create(
797 <React.Profiler id="outer" onRender={callback}>
798 <Yield renderTime={5} />
@@ -847,7 +843,6 @@ describe(`onRender`, () => {
843 expect(outerCall[5]).toBe(87); // commit time
844 });
845
850 - // @gate experimental || !enableSyncDefaultUpdates
846 it('should report the expected times when a high-pri update replaces a mount in-progress', () => {
847 const callback = jest.fn();
848
@@ -863,7 +858,7 @@ describe(`onRender`, () => {
858 // This partial render should take 10ms of simulated time.
859 let renderer;
860 if (gate(flags => flags.enableSyncDefaultUpdates)) {
866 - React.unstable_startTransition(() => {
861 + React.startTransition(() => {
862 renderer = ReactTestRenderer.create(
863 <React.Profiler id="test" onRender={callback}>
864 <Yield renderTime={10} />
@@ -914,7 +909,6 @@ describe(`onRender`, () => {
909 expect(callback).toHaveBeenCalledTimes(0);
910 });
911
917 - // @gate experimental || !enableSyncDefaultUpdates
912 it('should report the expected times when a high-priority update replaces a low-priority update', () => {
913 const callback = jest.fn();
914
@@ -951,7 +945,7 @@ describe(`onRender`, () => {
945 // Render a partially update, but don't finish.
946 // This partial render should take 3ms of simulated time.
947 if (gate(flags => flags.enableSyncDefaultUpdates)) {
954 - React.unstable_startTransition(() => {
948 + React.startTransition(() => {
949 renderer.update(
950 <React.Profiler id="test" onRender={callback}>
951 <Yield renderTime={3} />
@@ -1008,7 +1002,6 @@ describe(`onRender`, () => {
1002 expect(callback).toHaveBeenCalledTimes(1);
1003 });
1004
1011 - // @gate experimental || !enableSyncDefaultUpdates
1005 it('should report the expected times when a high-priority update interrupts a low-priority update', () => {
1006 const callback = jest.fn();
1007
@@ -1076,7 +1069,7 @@ describe(`onRender`, () => {
1069 // Render a partially update, but don't finish.
1070 // This partial render will take 10ms of actual render time.
1071 if (gate(flags => flags.enableSyncDefaultUpdates)) {
1079 - React.unstable_startTransition(() => {
1072 + React.startTransition(() => {
1073 first.setState({renderTime: 10});
1074 });
1075 } else {
packages/react/src/__tests__/ReactProfilerDevToolsIntegration-test.internal.js
+1 -2
@@ -138,7 +138,6 @@ describe('ReactProfiler DevTools integration', () => {
138 ).toBe(7);
139 });
140
141 - // @gate experimental || !enableSyncDefaultUpdates
141 it('regression test: #17159', () => {
142 function Text({text}) {
143 Scheduler.unstable_yieldValue(text);
@@ -157,7 +156,7 @@ describe('ReactProfiler DevTools integration', () => {
156 Scheduler.unstable_advanceTime(10000);
157 // Schedule an update.
158 if (gate(flags => flags.enableSyncDefaultUpdates)) {
160 - React.unstable_startTransition(() => {
159 + React.startTransition(() => {
160 root.update(<Text text="B" />);
161 });
162 } else {
packages/react/src/__tests__/ReactStrictMode-test.internal.js
-4
@@ -49,7 +49,6 @@ describe('ReactStrictMode', () => {
49 return null;
50 }
51
52 - // @gate experimental
52 it('should default to not strict', () => {
53 act(() => {
54 const container = document.createElement('div');
@@ -65,7 +64,6 @@ describe('ReactStrictMode', () => {
64 });
65
66 if (__DEV__) {
68 - // @gate experimental
67 it('should support enabling strict mode via createRoot option', () => {
68 act(() => {
69 const container = document.createElement('div');
@@ -87,7 +85,6 @@ describe('ReactStrictMode', () => {
85 ]);
86 });
87
90 - // @gate experimental
88 it('should include legacy + strict effects mode', () => {
89 act(() => {
90 const container = document.createElement('div');
@@ -111,7 +108,6 @@ describe('ReactStrictMode', () => {
108 ]);
109 });
110
114 - // @gate experimental
111 it('should allow level to be increased with nesting', () => {
112 act(() => {
113 const container = document.createElement('div');
packages/react/src/__tests__/ReactStrictMode-test.js
+3 -6
@@ -362,7 +362,6 @@ describe('Concurrent Mode', () => {
362 Scheduler = require('scheduler');
363 });
364
365 - // @gate experimental
365 it('should warn about unsafe legacy lifecycle methods anywhere in a StrictMode tree', () => {
366 function StrictRoot() {
367 return (
@@ -405,7 +404,7 @@ describe('Concurrent Mode', () => {
404 }
405
406 const container = document.createElement('div');
408 - const root = ReactDOM.unstable_createRoot(container);
407 + const root = ReactDOM.createRoot(container);
408 root.render(<StrictRoot />);
409 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
410 [
@@ -436,7 +435,6 @@ Please update the following components: App`,
435 Scheduler.unstable_flushAll();
436 });
437
439 - // @gate experimental
438 it('should coalesce warnings by lifecycle name', () => {
439 function StrictRoot() {
440 return (
@@ -468,7 +466,7 @@ Please update the following components: App`,
466 }
467
468 const container = document.createElement('div');
471 - const root = ReactDOM.unstable_createRoot(container);
469 + const root = ReactDOM.createRoot(container);
470 root.render(<StrictRoot />);
471
472 expect(() => {
@@ -526,7 +524,6 @@ Please update the following components: Parent`,
524 Scheduler.unstable_flushAll();
525 });
526
529 - // @gate experimental
527 it('should warn about components not present during the initial render', () => {
528 function StrictRoot({foo}) {
529 return <React.StrictMode>{foo ? <Foo /> : <Bar />}</React.StrictMode>;
@@ -545,7 +542,7 @@ Please update the following components: Parent`,
542 }
543
544 const container = document.createElement('div');
548 - const root = ReactDOM.unstable_createRoot(container);
545 + const root = ReactDOM.createRoot(container);
546 root.render(<StrictRoot foo={true} />);
547 expect(() =>
548 Scheduler.unstable_flushAll(),
packages/react/unstable-shared-subset.experimental.js
+17 -16
@@ -8,31 +8,32 @@
8 */
9
10 export {
11 + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
12 Children,
13 + Fragment,
14 + Profiler,
15 + StrictMode,
16 + Suspense,
17 + SuspenseList,
18 + cloneElement,
19 + createElement,
20 + createMutableSource as unstable_createMutableSource,
21 createRef,
22 forwardRef,
23 + isValidElement,
24 lazy,
25 memo,
26 + startTransition,
27 + unstable_DebugTracingMode,
28 + unstable_getCacheForType,
29 + unstable_useOpaqueIdentifier,
30 useCallback,
31 useContext,
32 useDebugValue,
33 + useDeferredValue,
34 + useDeferredValue as unstable_useDeferredValue,
35 useMemo,
36 useMutableSource as unstable_useMutableSource,
21 - createMutableSource as unstable_createMutableSource,
22 - Fragment,
23 - Profiler,
24 - StrictMode,
25 - Suspense,
26 - createElement,
27 - cloneElement,
28 - isValidElement,
37 + useTransition,
38 version,
30 - __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
31 - // exposeConcurrentModeAPIs
32 - useDeferredValue as unstable_useDeferredValue,
33 - SuspenseList as unstable_SuspenseList,
34 - unstable_useOpaqueIdentifier,
35 - unstable_getCacheForType,
36 - // enableDebugTracing
37 - unstable_DebugTracingMode,
39 } from './src/React';
packages/shared/ReactFeatureFlags.js
+3 -3
@@ -55,11 +55,11 @@ export const enableProfilerNestedUpdateScheduledHook = false;
55 export const enableUpdaterTracking = __PROFILE__;
56
57 // SSR experiments
58 -export const enableSuspenseServerRenderer = __EXPERIMENTAL__;
59 -export const enableSelectiveHydration = __EXPERIMENTAL__;
58 +export const enableSuspenseServerRenderer = true;
59 +export const enableSelectiveHydration = true;
60
61 // Flight experiments
62 -export const enableLazyElements = __EXPERIMENTAL__;
62 +export const enableLazyElements = true;
63 export const enableCache = __EXPERIMENTAL__;
64
65 // Only used in www builds.
packages/shared/forks/ReactFeatureFlags.www-dynamic.js
+1 -1
@@ -23,7 +23,7 @@ export const enableSuspenseLayoutEffectSemantics = __VARIANT__;
23 // Enable this flag to help with concurrent mode debugging.
24 // It logs information to the console about React scheduling, rendering, and commit phases.
25 //
26 -// NOTE: This feature will only work in DEV mode; all callsights are wrapped with __DEV__.
26 +// NOTE: This feature will only work in DEV mode; all callsites are wrapped with __DEV__.
27 export const enableDebugTracing = __EXPERIMENTAL__;
28 export const enableUpdaterTracking = false;
29
packages/use-subscription/src/__tests__/useSubscription-test.js
+4 -7
@@ -262,7 +262,6 @@ describe('useSubscription', () => {
262 expect(subscriptions).toHaveLength(2);
263 });
264
265 - // @gate experimental || !enableSyncDefaultUpdates
265 it('should ignore values emitted by a new subscribable until the commit phase', () => {
266 const log = [];
267
@@ -333,7 +332,7 @@ describe('useSubscription', () => {
332 // Start React update, but don't finish
333 act(() => {
334 if (gate(flags => flags.enableSyncDefaultUpdates)) {
336 - React.unstable_startTransition(() => {
335 + React.startTransition(() => {
336 renderer.update(<Parent observed={observableB} />);
337 });
338 } else {
@@ -370,7 +369,6 @@ describe('useSubscription', () => {
369 ]);
370 });
371
373 - // @gate experimental || !enableSyncDefaultUpdates
372 it('should not drop values emitted between updates', () => {
373 const log = [];
374
@@ -442,7 +440,7 @@ describe('useSubscription', () => {
440 // Start React update, but don't finish
441 act(() => {
442 if (gate(flags => flags.enableSyncDefaultUpdates)) {
445 - React.unstable_startTransition(() => {
443 + React.startTransition(() => {
444 renderer.update(<Parent observed={observableB} />);
445 });
446 } else {
@@ -576,7 +574,6 @@ describe('useSubscription', () => {
574 Scheduler.unstable_flushAll();
575 });
576
579 - // @gate experimental || !enableSyncDefaultUpdates
577 it('should not tear if a mutation occurs during a concurrent update', () => {
578 const input = document.createElement('input');
579
@@ -625,7 +622,7 @@ describe('useSubscription', () => {
622 // This update will not be eagerly evaluated,
623 // but useSubscription() should eagerly close over the updated value to avoid tearing.
624 if (gate(flags => flags.enableSyncDefaultUpdates)) {
628 - React.unstable_startTransition(() => {
625 + React.startTransition(() => {
626 mutate('C');
627 });
628 } else {
@@ -633,7 +630,7 @@ describe('useSubscription', () => {
630 }
631 expect(Scheduler).toFlushAndYieldThrough(['render:first:C']);
632 if (gate(flags => flags.enableSyncDefaultUpdates)) {
636 - React.unstable_startTransition(() => {
633 + React.startTransition(() => {
634 mutate('D');
635 });
636 } else {