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');