@samitouri / QOS-React-2 / commits / 15fb8c3045

createRoot API is no longer strict by default (#21417)

Brian Vaughn committed May 3, 2021 at 16:57 UTC 15fb8c3045064e13e81706a36bf0e4e419803c97
24 files changed +148 -370
packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
+4 -10
@@ -97,16 +97,10 @@ describe('ReactTestUtils.act()', () => {
97 });
98
99 // @gate experimental
100 - it('warns in concurrent mode', () => {
101 - expect(() => {
102 - const root = ReactDOM.unstable_createRoot(
103 - document.createElement('div'),
104 - );
105 - root.render(<App />);
106 - Scheduler.unstable_flushAll();
107 - }).toErrorDev([
108 - 'An update to App ran an effect, but was not wrapped in act(...)',
109 - ]);
100 + it('does not warn in concurrent mode', () => {
101 + const root = ReactDOM.unstable_createRoot(document.createElement('div'));
102 + root.render(<App />);
103 + Scheduler.unstable_flushAll();
104 });
105 });
106 });
packages/react-dom/src/client/ReactDOMRoot.js
-6
@@ -27,7 +27,6 @@ export type RootOptions = {
27 mutableSources?: Array<MutableSource<any>>,
28 ...
29 },
30 - unstable_strictModeLevel?: number,
30 unstable_concurrentUpdatesByDefault?: boolean,
31 ...
32 };
@@ -123,10 +122,6 @@ function createRootImpl(
122 options.hydrationOptions != null &&
123 options.hydrationOptions.mutableSources) ||
124 null;
126 - const strictModeLevelOverride =
127 - options != null && options.unstable_strictModeLevel != null
128 - ? options.unstable_strictModeLevel
129 - : null;
125
126 let concurrentUpdatesByDefaultOverride = null;
127 if (allowConcurrentByDefault) {
@@ -141,7 +136,6 @@ function createRootImpl(
136 tag,
137 hydrate,
138 hydrationCallbacks,
144 - strictModeLevelOverride,
139 concurrentUpdatesByDefaultOverride,
140 );
141 markContainerAsRoot(root.current, container);
packages/react-native-renderer/src/ReactFabric.js
+1 -1
@@ -207,7 +207,7 @@ function render(
207 if (!root) {
208 // TODO (bvaughn): If we decide to keep the wrapper component,
209 // We could create a wrapper for containerTag as well to reduce special casing.
210 - root = createContainer(containerTag, LegacyRoot, false, null, null, null);
210 + root = createContainer(containerTag, LegacyRoot, false, null, null);
211 roots.set(containerTag, root);
212 }
213 updateContainer(element, root, null, callback);
packages/react-native-renderer/src/ReactNativeRenderer.js
+1 -1
@@ -203,7 +203,7 @@ function render(
203 if (!root) {
204 // TODO (bvaughn): If we decide to keep the wrapper component,
205 // We could create a wrapper for containerTag as well to reduce special casing.
206 - root = createContainer(containerTag, LegacyRoot, false, null, null, null);
206 + root = createContainer(containerTag, LegacyRoot, false, null, null);
207 roots.set(containerTag, root);
208 }
209 updateContainer(element, root, null, callback);
packages/react-noop-renderer/src/createReactNoop.js
+1 -3
@@ -722,7 +722,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
722 if (!root) {
723 const container = {rootID: rootID, pendingChildren: [], children: []};
724 rootContainers.set(rootID, container);
725 - root = NoopRenderer.createContainer(container, tag, false, null, null);
725 + root = NoopRenderer.createContainer(container, tag, false, null);
726 roots.set(rootID, root);
727 }
728 return root.current.stateNode.containerInfo;
@@ -740,7 +740,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
740 ConcurrentRoot,
741 false,
742 null,
743 - null,
743 );
744 return {
745 _Scheduler: Scheduler,
@@ -767,7 +766,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
766 LegacyRoot,
767 false,
768 null,
770 - null,
769 );
770 return {
771 _Scheduler: Scheduler,
packages/react-reconciler/src/ReactFiber.new.js
+2 -16
@@ -422,27 +422,13 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
422
423 export function createHostRootFiber(
424 tag: RootTag,
425 - strictModeLevelOverride: null | number,
425 concurrentUpdatesByDefaultOverride: null | boolean,
426 ): Fiber {
427 let mode;
428 if (tag === ConcurrentRoot) {
429 mode = ConcurrentMode;
431 - if (strictModeLevelOverride !== null) {
432 - if (strictModeLevelOverride >= 1) {
433 - mode |= StrictLegacyMode;
434 - }
435 - if (enableStrictEffects) {
436 - if (strictModeLevelOverride >= 2) {
437 - mode |= StrictEffectsMode;
438 - }
439 - }
440 - } else {
441 - if (enableStrictEffects && createRootStrictEffectsByDefault) {
442 - mode |= StrictLegacyMode | StrictEffectsMode;
443 - } else {
444 - mode |= StrictLegacyMode;
445 - }
430 + if (enableStrictEffects && createRootStrictEffectsByDefault) {
431 + mode |= StrictLegacyMode | StrictEffectsMode;
432 }
433 if (
434 // We only use this flag for our repo tests to check both behaviors.
packages/react-reconciler/src/ReactFiber.old.js
+2 -16
@@ -422,27 +422,13 @@ export function resetWorkInProgress(workInProgress: Fiber, renderLanes: Lanes) {
422
423 export function createHostRootFiber(
424 tag: RootTag,
425 - strictModeLevelOverride: null | number,
425 concurrentUpdatesByDefaultOverride: null | boolean,
426 ): Fiber {
427 let mode;
428 if (tag === ConcurrentRoot) {
429 mode = ConcurrentMode;
431 - if (strictModeLevelOverride !== null) {
432 - if (strictModeLevelOverride >= 1) {
433 - mode |= StrictLegacyMode;
434 - }
435 - if (enableStrictEffects) {
436 - if (strictModeLevelOverride >= 2) {
437 - mode |= StrictEffectsMode;
438 - }
439 - }
440 - } else {
441 - if (enableStrictEffects && createRootStrictEffectsByDefault) {
442 - mode |= StrictLegacyMode | StrictEffectsMode;
443 - } else {
444 - mode |= StrictLegacyMode;
445 - }
430 + if (enableStrictEffects && createRootStrictEffectsByDefault) {
431 + mode |= StrictLegacyMode | StrictEffectsMode;
432 }
433 if (
434 // We only use this flag for our repo tests to check both behaviors.
packages/react-reconciler/src/ReactFiberReconciler.new.js
-2
@@ -248,7 +248,6 @@ export function createContainer(
248 tag: RootTag,
249 hydrate: boolean,
250 hydrationCallbacks: null | SuspenseHydrationCallbacks,
251 - strictModeLevelOverride: null | number,
251 concurrentUpdatesByDefaultOverride: null | boolean,
252 ): OpaqueRoot {
253 return createFiberRoot(
@@ -256,7 +255,6 @@ export function createContainer(
255 tag,
256 hydrate,
257 hydrationCallbacks,
259 - strictModeLevelOverride,
258 concurrentUpdatesByDefaultOverride,
259 );
260 }
packages/react-reconciler/src/ReactFiberReconciler.old.js
-2
@@ -248,7 +248,6 @@ export function createContainer(
248 tag: RootTag,
249 hydrate: boolean,
250 hydrationCallbacks: null | SuspenseHydrationCallbacks,
251 - strictModeLevelOverride: null | number,
251 concurrentUpdatesByDefaultOverride: null | boolean,
252 ): OpaqueRoot {
253 return createFiberRoot(
@@ -256,7 +255,6 @@ export function createContainer(
255 tag,
256 hydrate,
257 hydrationCallbacks,
259 - strictModeLevelOverride,
258 concurrentUpdatesByDefaultOverride,
259 );
260 }
packages/react-reconciler/src/ReactFiberRoot.new.js
-2
@@ -98,7 +98,6 @@ export function createFiberRoot(
98 tag: RootTag,
99 hydrate: boolean,
100 hydrationCallbacks: null | SuspenseHydrationCallbacks,
101 - strictModeLevelOverride: null | number,
101 concurrentUpdatesByDefaultOverride: null | boolean,
102 ): FiberRoot {
103 const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
@@ -110,7 +109,6 @@ export function createFiberRoot(
109 // stateNode is any.
110 const uninitializedFiber = createHostRootFiber(
111 tag,
113 - strictModeLevelOverride,
112 concurrentUpdatesByDefaultOverride,
113 );
114 root.current = uninitializedFiber;
packages/react-reconciler/src/ReactFiberRoot.old.js
-2
@@ -98,7 +98,6 @@ export function createFiberRoot(
98 tag: RootTag,
99 hydrate: boolean,
100 hydrationCallbacks: null | SuspenseHydrationCallbacks,
101 - strictModeLevelOverride: null | number,
101 concurrentUpdatesByDefaultOverride: null | boolean,
102 ): FiberRoot {
103 const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
@@ -110,7 +109,6 @@ export function createFiberRoot(
109 // stateNode is any.
110 const uninitializedFiber = createHostRootFiber(
111 tag,
113 - strictModeLevelOverride,
112 concurrentUpdatesByDefaultOverride,
113 );
114 root.current = uninitializedFiber;
packages/react-reconciler/src/__tests__/DebugTracing-test.internal.js
-2
@@ -282,7 +282,6 @@ describe('DebugTracing', () => {
282 expect(logs).toEqual([
283 `group: ⚛️ render (${DEFAULT_LANE_STRING})`,
284 `log: ⚛️ Example updated state (${DEFAULT_LANE_STRING})`,
285 - `log: ⚛️ Example updated state (${DEFAULT_LANE_STRING})`,
285 `groupEnd: ⚛️ render (${DEFAULT_LANE_STRING})`,
286 ]);
287 });
@@ -366,7 +365,6 @@ describe('DebugTracing', () => {
365 expect(logs).toEqual([
366 `group: ⚛️ render (${DEFAULT_LANE_STRING})`,
367 `log: ⚛️ Example updated state (${DEFAULT_LANE_STRING})`,
369 - `log: ⚛️ Example updated state (${DEFAULT_LANE_STRING})`, // debugRenderPhaseSideEffectsForStrictMode
368 `groupEnd: ⚛️ render (${DEFAULT_LANE_STRING})`,
369 ]);
370 });
packages/react-reconciler/src/__tests__/ReactHooksWithNoopRenderer-test.js
+7 -20
@@ -520,11 +520,7 @@ describe('ReactHooksWithNoopRenderer', () => {
520 </>,
521 );
522 expect(() =>
523 - expect(Scheduler).toFlushAndYield(
524 - __DEV__
525 - ? ['Foo [0]', 'Bar', 'Foo [2]']
526 - : ['Foo [0]', 'Bar', 'Foo [1]'],
527 - ),
523 + expect(Scheduler).toFlushAndYield(['Foo [0]', 'Bar', 'Foo [1]']),
524 ).toErrorDev([
525 'Cannot update a component (`Foo`) while rendering a ' +
526 'different component (`Bar`). To locate the bad setState() call inside `Bar`',
@@ -539,11 +535,7 @@ describe('ReactHooksWithNoopRenderer', () => {
535 <Bar triggerUpdate={true} />
536 </>,
537 );
542 - expect(Scheduler).toFlushAndYield(
543 - __DEV__
544 - ? ['Foo [2]', 'Bar', 'Foo [4]']
545 - : ['Foo [1]', 'Bar', 'Foo [2]'],
546 - );
538 + expect(Scheduler).toFlushAndYield(['Foo [1]', 'Bar', 'Foo [2]']);
539 });
540 });
541
@@ -1765,16 +1757,11 @@ describe('ReactHooksWithNoopRenderer', () => {
1757 return <Text text={'Count: ' + count} />;
1758 }
1759
1768 - // we explicitly wait for missing act() warnings here since
1769 - // it's a lot harder to simulate this condition inside an act scope
1770 - expect(() => {
1771 - ReactNoop.render(<Counter count={0} />, () =>
1772 - Scheduler.unstable_yieldValue('Sync effect'),
1773 - );
1774 - expect(Scheduler).toFlushAndYieldThrough(['Count: 0', 'Sync effect']);
1775 - expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]);
1776 - }).toErrorDev(['An update to Counter ran an effect']);
1777 -
1760 + ReactNoop.render(<Counter count={0} />, () =>
1761 + Scheduler.unstable_yieldValue('Sync effect'),
1762 + );
1763 + expect(Scheduler).toFlushAndYieldThrough(['Count: 0', 'Sync effect']);
1764 + expect(ReactNoop.getChildren()).toEqual([span('Count: 0')]);
1765 // A flush sync doesn't cause the passive effects to fire.
1766 // So we haven't added the other update yet.
1767 act(() => {
packages/react-reconciler/src/__tests__/ReactIncremental-test.js
+68 -153
@@ -1863,18 +1863,11 @@ describe('ReactIncremental', () => {
1863 </div>
1864 </Intl>,
1865 );
1866 - expect(() =>
1867 - expect(Scheduler).toFlushAndYield([
1868 - 'Intl {}',
1869 - 'ShowLocale {"locale":"fr"}',
1870 - 'ShowBoth {"locale":"fr"}',
1871 - ]),
1872 - ).toErrorDev(
1873 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
1874 - 'The old API will be supported in all 16.x releases, but applications ' +
1875 - 'using it should migrate to the new version.\n\n' +
1876 - 'Please update the following components: Intl, ShowBoth, ShowLocale',
1877 - );
1866 + expect(Scheduler).toFlushAndYield([
1867 + 'Intl {}',
1868 + 'ShowLocale {"locale":"fr"}',
1869 + 'ShowBoth {"locale":"fr"}',
1870 + ]);
1871
1872 ReactNoop.render(
1873 <Intl locale="de">
@@ -1921,28 +1914,21 @@ describe('ReactIncremental', () => {
1914 <ShowBoth />
1915 </Intl>,
1916 );
1924 - expect(() =>
1925 - expect(Scheduler).toFlushAndYield([
1926 - 'ShowLocale {"locale":"sv"}',
1927 - 'ShowBoth {"locale":"sv"}',
1928 - 'Intl {}',
1929 - 'ShowLocale {"locale":"en"}',
1930 - 'Router {}',
1931 - 'Indirection {}',
1932 - 'ShowLocale {"locale":"en"}',
1933 - 'ShowRoute {"route":"/about"}',
1934 - 'ShowNeither {}',
1935 - 'Intl {}',
1936 - 'ShowBoth {"locale":"ru","route":"/about"}',
1937 - 'ShowBoth {"locale":"en","route":"/about"}',
1938 - 'ShowBoth {"locale":"en"}',
1939 - ]),
1940 - ).toErrorDev(
1941 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
1942 - 'The old API will be supported in all 16.x releases, but applications ' +
1943 - 'using it should migrate to the new version.\n\n' +
1944 - 'Please update the following components: Router, ShowRoute',
1945 - );
1917 + expect(Scheduler).toFlushAndYield([
1918 + 'ShowLocale {"locale":"sv"}',
1919 + 'ShowBoth {"locale":"sv"}',
1920 + 'Intl {}',
1921 + 'ShowLocale {"locale":"en"}',
1922 + 'Router {}',
1923 + 'Indirection {}',
1924 + 'ShowLocale {"locale":"en"}',
1925 + 'ShowRoute {"route":"/about"}',
1926 + 'ShowNeither {}',
1927 + 'Intl {}',
1928 + 'ShowBoth {"locale":"ru","route":"/about"}',
1929 + 'ShowBoth {"locale":"en","route":"/about"}',
1930 + 'ShowBoth {"locale":"en"}',
1931 + ]);
1932 });
1933
1934 it('does not leak own context into context provider', () => {
@@ -1968,19 +1954,12 @@ describe('ReactIncremental', () => {
1954 }
1955
1956 ReactNoop.render(<Recurse />);
1971 - expect(() =>
1972 - expect(Scheduler).toFlushAndYield([
1973 - 'Recurse {}',
1974 - 'Recurse {"n":2}',
1975 - 'Recurse {"n":1}',
1976 - 'Recurse {"n":0}',
1977 - ]),
1978 - ).toErrorDev(
1979 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
1980 - 'The old API will be supported in all 16.x releases, but applications ' +
1981 - 'using it should migrate to the new version.\n\n' +
1982 - 'Please update the following components: Recurse',
1983 - );
1957 + expect(Scheduler).toFlushAndYield([
1958 + 'Recurse {}',
1959 + 'Recurse {"n":2}',
1960 + 'Recurse {"n":1}',
1961 + 'Recurse {"n":0}',
1962 + ]);
1963 });
1964
1965 if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) {
@@ -2020,10 +1999,6 @@ describe('ReactIncremental', () => {
1999 "If you can't use a class try assigning the prototype on the function as a workaround. " +
2000 '`Recurse.prototype = React.Component.prototype`. ' +
2001 "Don't use an arrow function since it cannot be called with `new` by React.",
2023 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2024 - 'The old API will be supported in all 16.x releases, but applications ' +
2025 - 'using it should migrate to the new version.\n\n' +
2026 - 'Please update the following components: Recurse',
2002 ]);
2003 });
2004 }
@@ -2092,18 +2067,11 @@ describe('ReactIncremental', () => {
2067 'ShowLocale {"locale":"fr"}',
2068 ]);
2069
2095 - expect(() =>
2096 - expect(Scheduler).toFlushAndYield([
2097 - 'ShowLocale {"locale":"fr"}',
2098 - 'Intl {}',
2099 - 'ShowLocale {"locale":"ru"}',
2100 - ]),
2101 - ).toErrorDev(
2102 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2103 - 'The old API will be supported in all 16.x releases, but applications ' +
2104 - 'using it should migrate to the new version.\n\n' +
2105 - 'Please update the following components: Intl, ShowLocale',
2106 - );
2070 + expect(Scheduler).toFlushAndYield([
2071 + 'ShowLocale {"locale":"fr"}',
2072 + 'Intl {}',
2073 + 'ShowLocale {"locale":"ru"}',
2074 + ]);
2075 });
2076
2077 it('reads context when setState is below the provider', () => {
@@ -2186,21 +2154,14 @@ describe('ReactIncremental', () => {
2154 </IndirectionFn>
2155 </Intl>,
2156 );
2189 - expect(() =>
2190 - expect(Scheduler).toFlushAndYield([
2191 - 'Intl:read {}',
2192 - 'Intl:provide {"locale":"fr"}',
2193 - 'IndirectionFn {}',
2194 - 'IndirectionClass {}',
2195 - 'ShowLocaleClass:read {"locale":"fr"}',
2196 - 'ShowLocaleFn:read {"locale":"fr"}',
2197 - ]),
2198 - ).toErrorDev(
2199 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2200 - 'The old API will be supported in all 16.x releases, but applications ' +
2201 - 'using it should migrate to the new version.\n\n' +
2202 - 'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn',
2203 - );
2157 + expect(Scheduler).toFlushAndYield([
2158 + 'Intl:read {}',
2159 + 'Intl:provide {"locale":"fr"}',
2160 + 'IndirectionFn {}',
2161 + 'IndirectionClass {}',
2162 + 'ShowLocaleClass:read {"locale":"fr"}',
2163 + 'ShowLocaleFn:read {"locale":"fr"}',
2164 + ]);
2165
2166 statefulInst.setState({x: 1});
2167 expect(Scheduler).toFlushWithoutYielding();
@@ -2287,21 +2248,14 @@ describe('ReactIncremental', () => {
2248 </IndirectionFn>
2249 </Stateful>,
2250 );
2290 - expect(() =>
2291 - expect(Scheduler).toFlushAndYield([
2292 - 'Intl:read {}',
2293 - 'Intl:provide {"locale":"fr"}',
2294 - 'IndirectionFn {}',
2295 - 'IndirectionClass {}',
2296 - 'ShowLocaleClass:read {"locale":"fr"}',
2297 - 'ShowLocaleFn:read {"locale":"fr"}',
2298 - ]),
2299 - ).toErrorDev(
2300 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2301 - 'The old API will be supported in all 16.x releases, but applications ' +
2302 - 'using it should migrate to the new version.\n\n' +
2303 - 'Please update the following components: Intl, ShowLocaleClass, ShowLocaleFn',
2304 - );
2251 + expect(Scheduler).toFlushAndYield([
2252 + 'Intl:read {}',
2253 + 'Intl:provide {"locale":"fr"}',
2254 + 'IndirectionFn {}',
2255 + 'IndirectionClass {}',
2256 + 'ShowLocaleClass:read {"locale":"fr"}',
2257 + 'ShowLocaleFn:read {"locale":"fr"}',
2258 + ]);
2259
2260 statefulInst.setState({locale: 'gr'});
2261 expect(Scheduler).toFlushAndYield([
@@ -2356,12 +2310,7 @@ describe('ReactIncremental', () => {
2310
2311 // Init
2312 ReactNoop.render(<Root />);
2359 - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2360 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2361 - 'The old API will be supported in all 16.x releases, but applications ' +
2362 - 'using it should migrate to the new version.\n\n' +
2363 - 'Please update the following components: Child',
2364 - );
2313 + expect(Scheduler).toFlushWithoutYielding();
2314
2315 // Trigger an update in the middle of the tree
2316 instance.setState({});
@@ -2407,12 +2356,7 @@ describe('ReactIncremental', () => {
2356
2357 // Init
2358 ReactNoop.render(<Root />);
2410 - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
2411 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2412 - 'The old API will be supported in all 16.x releases, but applications ' +
2413 - 'using it should migrate to the new version.\n\n' +
2414 - 'Please update the following components: ContextProvider',
2415 - );
2359 + expect(Scheduler).toFlushWithoutYielding();
2360
2361 // Trigger an update in the middle of the tree
2362 // This is necessary to reproduce the error as it currently exists.
@@ -2454,27 +2398,16 @@ describe('ReactIncremental', () => {
2398 }
2399
2400 ReactNoop.render(<MyComponent />);
2457 - expect(() =>
2458 - expect(Scheduler).toFlushAndYield([
2459 - 'render',
2460 - 'componentDidMount',
2461 - 'shouldComponentUpdate',
2462 - 'render',
2463 - 'componentDidUpdate',
2464 - 'shouldComponentUpdate',
2465 - 'render',
2466 - 'componentDidUpdate',
2467 - ]),
2468 - ).toErrorDev(
2469 - [
2470 - 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended',
2471 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2472 - 'The old API will be supported in all 16.x releases, but applications ' +
2473 - 'using it should migrate to the new version.\n\n' +
2474 - 'Please update the following components: MyComponent',
2475 - ],
2476 - {withoutStack: 1},
2477 - );
2401 + expect(Scheduler).toFlushAndYield([
2402 + 'render',
2403 + 'componentDidMount',
2404 + 'shouldComponentUpdate',
2405 + 'render',
2406 + 'componentDidUpdate',
2407 + 'shouldComponentUpdate',
2408 + 'render',
2409 + 'componentDidUpdate',
2410 + ]);
2411 });
2412
2413 xit('should reuse memoized work if pointers are updated before calling lifecycles', () => {
@@ -2604,12 +2537,7 @@ describe('ReactIncremental', () => {
2537 </TopContextProvider>,
2538 );
2539
2607 - expect(() => expect(Scheduler).toFlushAndYield(['count:0'])).toErrorDev(
2608 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2609 - 'The old API will be supported in all 16.x releases, but applications ' +
2610 - 'using it should migrate to the new version.\n\n' +
2611 - 'Please update the following components: Child, TopContextProvider',
2612 - );
2540 + expect(Scheduler).toFlushAndYield(['count:0']);
2541 instance.updateCount();
2542 expect(Scheduler).toFlushAndYield(['count:1']);
2543 });
@@ -2664,12 +2592,7 @@ describe('ReactIncremental', () => {
2592 </TopContextProvider>,
2593 );
2594
2667 - expect(() => expect(Scheduler).toFlushAndYield(['count:0'])).toErrorDev(
2668 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2669 - 'The old API will be supported in all 16.x releases, but applications ' +
2670 - 'using it should migrate to the new version.\n\n' +
2671 - 'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2672 - );
2595 + expect(Scheduler).toFlushAndYield(['count:0']);
2596 instance.updateCount();
2597 expect(Scheduler).toFlushAndYield(['count:1']);
2598 });
@@ -2733,12 +2656,7 @@ describe('ReactIncremental', () => {
2656 </TopContextProvider>,
2657 );
2658
2736 - expect(() => expect(Scheduler).toFlushAndYield(['count:0'])).toErrorDev(
2737 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2738 - 'The old API will be supported in all 16.x releases, but applications ' +
2739 - 'using it should migrate to the new version.\n\n' +
2740 - 'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2741 - );
2659 + expect(Scheduler).toFlushAndYield(['count:0']);
2660 instance.updateCount();
2661 expect(Scheduler).toFlushWithoutYielding();
2662 });
@@ -2814,14 +2732,7 @@ describe('ReactIncremental', () => {
2732 </TopContextProvider>,
2733 );
2734
2817 - expect(() =>
2818 - expect(Scheduler).toFlushAndYield(['count:0, name:brian']),
2819 - ).toErrorDev(
2820 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
2821 - 'The old API will be supported in all 16.x releases, but applications ' +
2822 - 'using it should migrate to the new version.\n\n' +
2823 - 'Please update the following components: Child, MiddleContextProvider, TopContextProvider',
2824 - );
2735 + expect(Scheduler).toFlushAndYield(['count:0, name:brian']);
2736 topInstance.updateCount();
2737 expect(Scheduler).toFlushWithoutYielding();
2738 middleInstance.updateName('not brian');
@@ -2933,7 +2844,11 @@ describe('ReactIncremental', () => {
2844 return this.state.didError ? null : <Thing />;
2845 }
2846 }
2936 - ReactNoop.render(<Boundary />);
2847 + ReactNoop.render(
2848 + <React.StrictMode>
2849 + <Boundary />
2850 + </React.StrictMode>,
2851 + );
2852 expect(() => {
2853 expect(Scheduler).toFlushWithoutYielding();
2854 }).toErrorDev([
packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js
+1 -10
@@ -1286,12 +1286,7 @@ describe('ReactIncrementalErrorHandling', () => {
1286 <Connector />
1287 </Provider>,
1288 );
1289 - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
1290 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
1291 - 'The old API will be supported in all 16.x releases, but ' +
1292 - 'applications using it should migrate to the new version.\n\n' +
1293 - 'Please update the following components: Connector, Provider',
1294 - );
1289 + expect(Scheduler).toFlushWithoutYielding();
1290
1291 // If the context stack does not unwind, span will get 'abcde'
1292 expect(ReactNoop.getChildren()).toEqual([span('a')]);
@@ -1843,10 +1838,6 @@ describe('ReactIncrementalErrorHandling', () => {
1838 "If you can't use a class try assigning the prototype on the function as a workaround. " +
1839 '`Provider.prototype = React.Component.prototype`. ' +
1840 "Don't use an arrow function since it cannot be called with `new` by React.",
1846 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
1847 - 'The old API will be supported in all 16.x releases, but ' +
1848 - 'applications using it should migrate to the new version.\n\n' +
1849 - 'Please update the following components: Provider',
1841 ]);
1842 });
1843 }
packages/react-reconciler/src/__tests__/ReactIncrementalReflection-test.js
+3 -21
@@ -78,12 +78,7 @@ describe('ReactIncrementalReflection', () => {
78 expect(instances[0]._isMounted()).toBe(false);
79
80 // Render the rest and commit the updates.
81 - expect(() =>
82 - expect(Scheduler).toFlushAndYield(['componentDidMount: true']),
83 - ).toErrorDev(
84 - 'Using UNSAFE_componentWillMount in strict mode is not recommended',
85 - {withoutStack: true},
86 - );
81 + expect(Scheduler).toFlushAndYield(['componentDidMount: true']);
82
83 expect(instances[0]._isMounted()).toBe(true);
84 });
@@ -120,12 +115,7 @@ describe('ReactIncrementalReflection', () => {
115 }
116
117 ReactNoop.render(<Foo mount={true} />);
123 - expect(() =>
124 - expect(Scheduler).toFlushAndYield(['Component']),
125 - ).toErrorDev(
126 - 'Using UNSAFE_componentWillMount in strict mode is not recommended',
127 - {withoutStack: true},
128 - );
118 + expect(Scheduler).toFlushAndYield(['Component']);
119
120 expect(instances[0]._isMounted()).toBe(true);
121
@@ -238,15 +228,7 @@ describe('ReactIncrementalReflection', () => {
228 // not find any host nodes in it.
229 expect(findInstance(classInstance)).toBe(null);
230
241 - expect(() =>
242 - expect(Scheduler).toFlushAndYield([['componentDidMount', span()]]),
243 - ).toErrorDev(
244 - [
245 - 'Using UNSAFE_componentWillMount in strict mode is not recommended',
246 - 'Using UNSAFE_componentWillUpdate in strict mode is not recommended',
247 - ],
248 - {withoutStack: true},
249 - );
231 + expect(Scheduler).toFlushAndYield([['componentDidMount', span()]]);
232
233 const hostSpan = classInstance.span;
234 expect(hostSpan).toBeDefined();
packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js
+1 -3
@@ -1308,9 +1308,7 @@ describe('ReactIncrementalSideEffects', () => {
1308 }
1309
1310 ReactNoop.render(<Foo />);
1311 - expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev(
1312 - 'Warning: A string ref, "bar", has been found within a strict mode tree.',
1313 - );
1311 + expect(Scheduler).toFlushWithoutYielding();
1312
1313 expect(fooInstance.refs.bar.test).toEqual('test');
1314 });
packages/react-reconciler/src/__tests__/ReactIncrementalUpdates-test.js
+1 -6
@@ -402,12 +402,7 @@ describe('ReactIncrementalUpdates', () => {
402 }
403 }
404 ReactNoop.render(<Foo />);
405 - expect(() =>
406 - expect(Scheduler).toFlushAndYield(['render']),
407 - ).toErrorDev(
408 - 'Using UNSAFE_componentWillReceiveProps in strict mode is not recommended',
409 - {withoutStack: true},
410 - );
405 + expect(Scheduler).toFlushAndYield(['render']);
406
407 ReactNoop.flushSync(() => {
408 instance.setState({a: 'a'});
packages/react-reconciler/src/__tests__/ReactNewContext-test.js
+1 -10
@@ -953,14 +953,7 @@ describe('ReactNewContext', () => {
953 </App>
954 </LegacyProvider>,
955 );
956 - expect(() => {
957 - expect(Scheduler).toFlushAndYield(['LegacyProvider', 'App', 'Child']);
958 - }).toErrorDev(
959 - 'Legacy context API has been detected within a strict-mode tree.\n\n' +
960 - 'The old API will be supported in all 16.x releases, but applications ' +
961 - 'using it should migrate to the new version.\n\n' +
962 - 'Please update the following components: LegacyProvider',
963 - );
956 + expect(Scheduler).toFlushAndYield(['LegacyProvider', 'App', 'Child']);
957 expect(ReactNoop.getChildren()).toEqual([span('Child')]);
958
959 // Update App with same value (should bail out)
@@ -1244,8 +1237,6 @@ describe('ReactNewContext', () => {
1237
1238 ReactNoop.render(<Cls />);
1239 expect(() => expect(Scheduler).toFlushWithoutYielding()).toErrorDev([
1247 - 'Context can only be read while React is rendering',
1248 - // A second warning comes from to setStates being added to the queue.
1240 'Context can only be read while React is rendering',
1241 'Cannot update during an existing state transition',
1242 ]);
packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js
+6 -1
@@ -1836,9 +1836,14 @@ describe('useMutableSource', () => {
1836 return null;
1837 }
1838
1839 + // TODO The mechanism for this type of detection relies on StrictMode double rendering.
1840 expect(() => {
1841 act(() => {
1841 - ReactNoop.render(<MutateDuringRead />);
1842 + ReactNoop.render(
1843 + <React.StrictMode>
1844 + <MutateDuringRead />
1845 + </React.StrictMode>,
1846 + );
1847 });
1848 }).toThrow(
1849 'A mutable source was mutated while the MutateDuringRead component ' +
packages/react-test-renderer/src/ReactTestRenderer.js
-6
@@ -58,7 +58,6 @@ const {IsSomeRendererActing} = ReactSharedInternals;
58 type TestRendererOptions = {
59 createNodeMock: (element: React$Element<any>) => any,
60 unstable_isConcurrent: boolean,
61 - unstable_strictModeLevel: number,
61 unstable_concurrentUpdatesByDefault: boolean,
62 ...
63 };
@@ -437,7 +436,6 @@ function propsMatch(props: Object, filter: Object): boolean {
436 function create(element: React$Element<any>, options: TestRendererOptions) {
437 let createNodeMock = defaultTestOptions.createNodeMock;
438 let isConcurrent = false;
440 - let strictModeLevel = null;
439 let concurrentUpdatesByDefault = null;
440 if (typeof options === 'object' && options !== null) {
441 if (typeof options.createNodeMock === 'function') {
@@ -446,9 +444,6 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
444 if (options.unstable_isConcurrent === true) {
445 isConcurrent = true;
446 }
449 - if (options.unstable_strictModeLevel !== undefined) {
450 - strictModeLevel = options.unstable_strictModeLevel;
451 - }
447 if (allowConcurrentByDefault) {
448 if (options.unstable_concurrentUpdatesByDefault !== undefined) {
449 concurrentUpdatesByDefault =
@@ -466,7 +461,6 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
461 isConcurrent ? ConcurrentRoot : LegacyRoot,
462 false,
463 null,
469 - strictModeLevel,
464 concurrentUpdatesByDefault,
465 );
466 invariant(root != null, 'something went wrong');
packages/react/src/__tests__/ReactStrictMode-test.internal.js
+4 -44
@@ -50,12 +50,10 @@ describe('ReactStrictMode', () => {
50 }
51
52 // @gate experimental
53 - it('should support overriding default via createRoot option', () => {
53 + it('should default to not strict', () => {
54 act(() => {
55 const container = document.createElement('div');
56 - const root = ReactDOM.createRoot(container, {
57 - unstable_strictModeLevel: 0,
58 - });
56 + const root = ReactDOM.createRoot(container);
57 root.render(<Component label="A" />);
58 });
59
@@ -66,27 +64,6 @@ describe('ReactStrictMode', () => {
64 ]);
65 });
66
69 - // @gate experimental
70 - it('should disable strict mode if level 0 is specified', () => {
71 - act(() => {
72 - const container = document.createElement('div');
73 - const root = ReactDOM.createRoot(container, {
74 - unstable_strictModeLevel: 0,
75 - });
76 - root.render(
77 - <React.StrictMode unstable_level={0}>
78 - <Component label="A" />
79 - </React.StrictMode>,
80 - );
81 - });
82 -
83 - expect(log).toEqual([
84 - 'A: render',
85 - 'A: useLayoutEffect mount',
86 - 'A: useEffect mount',
87 - ]);
88 - });
89 -
67 if (__DEV__) {
68 // @gate experimental
69 it('should default to level 1 (legacy mode)', () => {
@@ -156,9 +133,7 @@ describe('ReactStrictMode', () => {
133 it('should allow level to be increased with nesting', () => {
134 act(() => {
135 const container = document.createElement('div');
159 - const root = ReactDOM.createRoot(container, {
160 - unstable_strictModeLevel: 0,
161 - });
136 + const root = ReactDOM.createRoot(container);
137 root.render(
138 <>
139 <Component label="A" />
@@ -197,9 +172,7 @@ describe('ReactStrictMode', () => {
172 it('should not allow level to be decreased with nesting', () => {
173 act(() => {
174 const container = document.createElement('div');
200 - const root = ReactDOM.createRoot(container, {
201 - unstable_strictModeLevel: 2,
202 - });
175 + const root = ReactDOM.createRoot(container);
176 root.render(
177 <>
178 <Component label="A" />
@@ -216,7 +189,6 @@ describe('ReactStrictMode', () => {
189 });
190
191 expect(log).toEqual([
219 - 'A: render',
192 'A: render',
193 'B: render',
194 'B: render',
@@ -228,18 +200,6 @@ describe('ReactStrictMode', () => {
200 'A: useEffect mount',
201 'B: useEffect mount',
202 'C: useEffect mount',
231 - 'A: useLayoutEffect unmount',
232 - 'B: useLayoutEffect unmount',
233 - 'C: useLayoutEffect unmount',
234 - 'A: useEffect unmount',
235 - 'B: useEffect unmount',
236 - 'C: useEffect unmount',
237 - 'A: useLayoutEffect mount',
238 - 'B: useLayoutEffect mount',
239 - 'C: useLayoutEffect mount',
240 - 'A: useEffect mount',
241 - 'B: useEffect mount',
242 - 'C: useEffect mount',
203 ]);
204 });
205 }
packages/react/src/__tests__/ReactStrictMode-test.js
+31 -19
@@ -363,8 +363,15 @@ describe('Concurrent Mode', () => {
363 });
364
365 // @gate experimental
366 - it('should warn about unsafe legacy lifecycle methods anywhere in the tree', () => {
367 - class AsyncRoot extends React.Component {
366 + it('should warn about unsafe legacy lifecycle methods anywhere in a StrictMode tree', () => {
367 + function StrictRoot() {
368 + return (
369 + <React.StrictMode>
370 + <App />
371 + </React.StrictMode>
372 + );
373 + }
374 + class App extends React.Component {
375 UNSAFE_componentWillMount() {}
376 UNSAFE_componentWillUpdate() {}
377 render() {
@@ -399,7 +406,7 @@ describe('Concurrent Mode', () => {
406
407 const container = document.createElement('div');
408 const root = ReactDOM.unstable_createRoot(container);
402 - root.render(<AsyncRoot />);
409 + root.render(<StrictRoot />);
410 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
411 [
412 /* eslint-disable max-len */
@@ -407,7 +414,7 @@ describe('Concurrent Mode', () => {
414
415 * Move code with side effects to componentDidMount, and set initial state in the constructor.
416
410 -Please update the following components: AsyncRoot`,
417 +Please update the following components: App`,
418 `Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.
419
420 * Move data fetching code or side effects to componentDidUpdate.
@@ -418,20 +425,27 @@ Please update the following components: Bar, Foo`,
425
426 * Move data fetching code or side effects to componentDidUpdate.
427
421 -Please update the following components: AsyncRoot`,
428 +Please update the following components: App`,
429 /* eslint-enable max-len */
430 ],
431 {withoutStack: true},
432 );
433
434 // Dedupe
428 - root.render(<AsyncRoot />);
435 + root.render(<App />);
436 Scheduler.unstable_flushAll();
437 });
438
439 // @gate experimental
440 it('should coalesce warnings by lifecycle name', () => {
434 - class AsyncRoot extends React.Component {
441 + function StrictRoot() {
442 + return (
443 + <React.StrictMode>
444 + <App />
445 + </React.StrictMode>
446 + );
447 + }
448 + class App extends React.Component {
449 UNSAFE_componentWillMount() {}
450 UNSAFE_componentWillUpdate() {}
451 render() {
@@ -455,7 +469,7 @@ Please update the following components: AsyncRoot`,
469
470 const container = document.createElement('div');
471 const root = ReactDOM.unstable_createRoot(container);
458 - root.render(<AsyncRoot />);
472 + root.render(<StrictRoot />);
473
474 expect(() => {
475 expect(() => Scheduler.unstable_flushAll()).toErrorDev(
@@ -465,7 +479,7 @@ Please update the following components: AsyncRoot`,
479
480 * Move code with side effects to componentDidMount, and set initial state in the constructor.
481
468 -Please update the following components: AsyncRoot`,
482 +Please update the following components: App`,
483 `Warning: Using UNSAFE_componentWillReceiveProps in strict mode is not recommended and may indicate bugs in your code. See https://reactjs.org/link/unsafe-component-lifecycles for details.
484
485 * Move data fetching code or side effects to componentDidUpdate.
@@ -476,7 +490,7 @@ Please update the following components: Child`,
490
491 * Move data fetching code or side effects to componentDidUpdate.
492
479 -Please update the following components: AsyncRoot`,
493 +Please update the following components: App`,
494 /* eslint-enable max-len */
495 ],
496 {withoutStack: true},
@@ -508,16 +522,14 @@ Please update the following components: Parent`,
522 {withoutStack: true},
523 );
524 // Dedupe
511 - root.render(<AsyncRoot />);
525 + root.render(<StrictRoot />);
526 Scheduler.unstable_flushAll();
527 });
528
529 // @gate experimental
530 it('should warn about components not present during the initial render', () => {
517 - class AsyncRoot extends React.Component {
518 - render() {
519 - return this.props.foo ? <Foo /> : <Bar />;
520 - }
531 + function StrictRoot({foo}) {
532 + return <React.StrictMode>{foo ? <Foo /> : <Bar />}</React.StrictMode>;
533 }
534 class Foo extends React.Component {
535 UNSAFE_componentWillMount() {}
@@ -534,7 +546,7 @@ Please update the following components: Parent`,
546
547 const container = document.createElement('div');
548 const root = ReactDOM.unstable_createRoot(container);
537 - root.render(<AsyncRoot foo={true} />);
549 + root.render(<StrictRoot foo={true} />);
550 expect(() =>
551 Scheduler.unstable_flushAll(),
552 ).toErrorDev(
@@ -542,7 +554,7 @@ Please update the following components: Parent`,
554 {withoutStack: true},
555 );
556
545 - root.render(<AsyncRoot foo={false} />);
557 + root.render(<StrictRoot foo={false} />);
558 expect(() =>
559 Scheduler.unstable_flushAll(),
560 ).toErrorDev(
@@ -551,9 +563,9 @@ Please update the following components: Parent`,
563 );
564
565 // Dedupe
554 - root.render(<AsyncRoot foo={true} />);
566 + root.render(<StrictRoot foo={true} />);
567 Scheduler.unstable_flushAll();
556 - root.render(<AsyncRoot foo={false} />);
568 + root.render(<StrictRoot foo={false} />);
569 Scheduler.unstable_flushAll();
570 });
571
packages/react/src/__tests__/forwardRef-test.js
+14 -14
@@ -287,11 +287,11 @@ describe('forwardRef', () => {
287
288 ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
289 expect(Scheduler).toFlushWithoutYielding();
290 - expect(renderCount).toBe(__DEV__ ? 2 : 1);
290 + expect(renderCount).toBe(1);
291
292 ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
293 expect(Scheduler).toFlushWithoutYielding();
294 - expect(renderCount).toBe(__DEV__ ? 4 : 2);
294 + expect(renderCount).toBe(2);
295 });
296
297 it('should bailout if forwardRef is wrapped in memo', () => {
@@ -310,13 +310,13 @@ describe('forwardRef', () => {
310
311 ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
312 expect(Scheduler).toFlushWithoutYielding();
313 - expect(renderCount).toBe(__DEV__ ? 2 : 1);
313 + expect(renderCount).toBe(1);
314
315 expect(ref.current.type).toBe('div');
316
317 ReactNoop.render(<RefForwardingComponent ref={ref} optional="foo" />);
318 expect(Scheduler).toFlushWithoutYielding();
319 - expect(renderCount).toBe(__DEV__ ? 2 : 1);
319 + expect(renderCount).toBe(1);
320
321 const differentRef = React.createRef();
322
@@ -324,14 +324,14 @@ describe('forwardRef', () => {
324 <RefForwardingComponent ref={differentRef} optional="foo" />,
325 );
326 expect(Scheduler).toFlushWithoutYielding();
327 - expect(renderCount).toBe(__DEV__ ? 4 : 2);
327 + expect(renderCount).toBe(2);
328
329 expect(ref.current).toBe(null);
330 expect(differentRef.current.type).toBe('div');
331
332 ReactNoop.render(<RefForwardingComponent ref={ref} optional="bar" />);
333 expect(Scheduler).toFlushWithoutYielding();
334 - expect(renderCount).toBe(__DEV__ ? 6 : 3);
334 + expect(renderCount).toBe(3);
335 });
336
337 it('should custom memo comparisons to compose', () => {
@@ -351,19 +351,19 @@ describe('forwardRef', () => {
351
352 ReactNoop.render(<RefForwardingComponent ref={ref} a="0" b="0" c="1" />);
353 expect(Scheduler).toFlushWithoutYielding();
354 - expect(renderCount).toBe(__DEV__ ? 2 : 1);
354 + expect(renderCount).toBe(1);
355
356 expect(ref.current.type).toBe('div');
357
358 // Changing either a or b rerenders
359 ReactNoop.render(<RefForwardingComponent ref={ref} a="0" b="1" c="1" />);
360 expect(Scheduler).toFlushWithoutYielding();
361 - expect(renderCount).toBe(__DEV__ ? 4 : 2);
361 + expect(renderCount).toBe(2);
362
363 // Changing c doesn't rerender
364 ReactNoop.render(<RefForwardingComponent ref={ref} a="0" b="1" c="2" />);
365 expect(Scheduler).toFlushWithoutYielding();
366 - expect(renderCount).toBe(__DEV__ ? 4 : 2);
366 + expect(renderCount).toBe(2);
367
368 const ComposedMemo = React.memo(
369 RefForwardingComponent,
@@ -372,29 +372,29 @@ describe('forwardRef', () => {
372
373 ReactNoop.render(<ComposedMemo ref={ref} a="0" b="0" c="0" />);
374 expect(Scheduler).toFlushWithoutYielding();
375 - expect(renderCount).toBe(__DEV__ ? 6 : 3);
375 + expect(renderCount).toBe(3);
376
377 // Changing just b no longer updates
378 ReactNoop.render(<ComposedMemo ref={ref} a="0" b="1" c="0" />);
379 expect(Scheduler).toFlushWithoutYielding();
380 - expect(renderCount).toBe(__DEV__ ? 6 : 3);
380 + expect(renderCount).toBe(3);
381
382 // Changing just a and c updates
383 ReactNoop.render(<ComposedMemo ref={ref} a="2" b="2" c="2" />);
384 expect(Scheduler).toFlushWithoutYielding();
385 - expect(renderCount).toBe(__DEV__ ? 8 : 4);
385 + expect(renderCount).toBe(4);
386
387 // Changing just c does not update
388 ReactNoop.render(<ComposedMemo ref={ref} a="2" b="2" c="3" />);
389 expect(Scheduler).toFlushWithoutYielding();
390 - expect(renderCount).toBe(__DEV__ ? 8 : 4);
390 + expect(renderCount).toBe(4);
391
392 // Changing ref still rerenders
393 const differentRef = React.createRef();
394
395 ReactNoop.render(<ComposedMemo ref={differentRef} a="2" b="2" c="3" />);
396 expect(Scheduler).toFlushWithoutYielding();
397 - expect(renderCount).toBe(__DEV__ ? 10 : 5);
397 + expect(renderCount).toBe(5);
398
399 expect(ref.current).toBe(null);
400 expect(differentRef.current.type).toBe('div');