@samitouri / QOS-React / commits / bd0a963445

Throw when `act` is used in production (#21686)

Upgrades the deprecation warning to a runtime error. I did it this way instead of removing the export so the type is the same in both builds. It will get dead code eliminated regardless.

Andrew Clark committed Jun 16, 2021 at 16:29 UTC bd0a963445715f2963d4a9e3a0485e56cbe60653
15 files changed +87 -92
fixtures/legacy-jsx-runtimes/setupTests.js
-10
@@ -33,16 +33,6 @@ function shouldIgnoreConsoleError(format, args) {
33 // They are noisy too so we'll try to ignore them.
34 return true;
35 }
36 - if (
37 - format.indexOf(
38 - 'act(...) is not supported in production builds of React'
39 - ) === 0
40 - ) {
41 - // We don't yet support act() for prod builds, and warn for it.
42 - // But we'd like to use act() ourselves for prod builds.
43 - // Let's ignore the warning and #yolo.
44 - return true;
45 - }
36 }
37 // Looks legit
38 return false;
packages/react-dom/src/__tests__/ReactTestUtilsAct-test.js
+28 -18
@@ -135,6 +135,7 @@ function runActTests(label, render, unmount, rerender) {
135 });
136
137 describe('sync', () => {
138 + // @gate __DEV__
139 it('can use act to flush effects', () => {
140 function App() {
141 React.useEffect(() => {
@@ -150,6 +151,7 @@ function runActTests(label, render, unmount, rerender) {
151 expect(Scheduler).toHaveYielded([100]);
152 });
153
154 + // @gate __DEV__
155 it('flushes effects on every call', async () => {
156 function App() {
157 const [ctr, setCtr] = React.useState(0);
@@ -186,6 +188,7 @@ function runActTests(label, render, unmount, rerender) {
188 expect(button.innerHTML).toBe('5');
189 });
190
191 + // @gate __DEV__
192 it("should keep flushing effects until they're done", () => {
193 function App() {
194 const [ctr, setCtr] = React.useState(0);
@@ -204,6 +207,7 @@ function runActTests(label, render, unmount, rerender) {
207 expect(container.innerHTML).toBe('5');
208 });
209
210 + // @gate __DEV__
211 it('should flush effects only on exiting the outermost act', () => {
212 function App() {
213 React.useEffect(() => {
@@ -224,6 +228,7 @@ function runActTests(label, render, unmount, rerender) {
228 expect(Scheduler).toHaveYielded([0]);
229 });
230
231 + // @gate __DEV__
232 it('warns if a setState is called outside of act(...)', () => {
233 let setValue = null;
234 function App() {
@@ -250,6 +255,7 @@ function runActTests(label, render, unmount, rerender) {
255 jest.useRealTimers();
256 });
257
258 + // @gate __DEV__
259 it('lets a ticker update', () => {
260 function App() {
261 const [toggle, setToggle] = React.useState(0);
@@ -272,6 +278,7 @@ function runActTests(label, render, unmount, rerender) {
278 expect(container.innerHTML).toBe('1');
279 });
280
281 + // @gate __DEV__
282 it('can use the async version to catch microtasks', async () => {
283 function App() {
284 const [toggle, setToggle] = React.useState(0);
@@ -294,6 +301,7 @@ function runActTests(label, render, unmount, rerender) {
301 expect(container.innerHTML).toBe('1');
302 });
303
304 + // @gate __DEV__
305 it('can handle cascading promises with fake timers', async () => {
306 // this component triggers an effect, that waits a tick,
307 // then sets state. repeats this 5 times.
@@ -317,6 +325,7 @@ function runActTests(label, render, unmount, rerender) {
325 expect(container.innerHTML).toBe('5');
326 });
327
328 + // @gate __DEV__
329 it('flushes immediate re-renders with act', () => {
330 function App() {
331 const [ctr, setCtr] = React.useState(0);
@@ -346,6 +355,7 @@ function runActTests(label, render, unmount, rerender) {
355 });
356 });
357
358 + // @gate __DEV__
359 it('warns if you return a value inside act', () => {
360 expect(() => act(() => null)).toErrorDev(
361 [
@@ -361,6 +371,7 @@ function runActTests(label, render, unmount, rerender) {
371 );
372 });
373
374 + // @gate __DEV__
375 it('warns if you try to await a sync .act call', () => {
376 expect(() => act(() => {}).then(() => {})).toErrorDev(
377 [
@@ -372,6 +383,7 @@ function runActTests(label, render, unmount, rerender) {
383 });
384
385 describe('asynchronous tests', () => {
386 + // @gate __DEV__
387 it('works with timeouts', async () => {
388 function App() {
389 const [ctr, setCtr] = React.useState(0);
@@ -396,6 +408,7 @@ function runActTests(label, render, unmount, rerender) {
408 expect(container.innerHTML).toBe('1');
409 });
410
411 + // @gate __DEV__
412 it('flushes microtasks before exiting', async () => {
413 function App() {
414 const [ctr, setCtr] = React.useState(0);
@@ -418,6 +431,7 @@ function runActTests(label, render, unmount, rerender) {
431 expect(container.innerHTML).toEqual('1');
432 });
433
434 + // @gate __DEV__
435 it('warns if you do not await an act call', async () => {
436 spyOnDevAndProd(console, 'error');
437 act(async () => {});
@@ -431,6 +445,7 @@ function runActTests(label, render, unmount, rerender) {
445 }
446 });
447
448 + // @gate __DEV__
449 it('warns if you try to interleave multiple act calls', async () => {
450 spyOnDevAndProd(console, 'error');
451 // let's try to cheat and spin off a 'thread' with an act call
@@ -450,6 +465,7 @@ function runActTests(label, render, unmount, rerender) {
465 }
466 });
467
468 + // @gate __DEV__
469 it('async commits and effects are guaranteed to be flushed', async () => {
470 function App() {
471 const [state, setState] = React.useState(0);
@@ -475,6 +491,7 @@ function runActTests(label, render, unmount, rerender) {
491 expect(container.innerHTML).toBe('1');
492 });
493
494 + // @gate __DEV__
495 it('can handle cascading promises', async () => {
496 // this component triggers an effect, that waits a tick,
497 // then sets state. repeats this 5 times.
@@ -501,6 +518,7 @@ function runActTests(label, render, unmount, rerender) {
518 });
519
520 describe('error propagation', () => {
521 + // @gate __DEV__
522 it('propagates errors - sync', () => {
523 let err;
524 try {
@@ -515,6 +533,7 @@ function runActTests(label, render, unmount, rerender) {
533 }
534 });
535
536 + // @gate __DEV__
537 it('should propagate errors from effects - sync', () => {
538 function App() {
539 React.useEffect(() => {
@@ -536,6 +555,7 @@ function runActTests(label, render, unmount, rerender) {
555 }
556 });
557
558 + // @gate __DEV__
559 it('propagates errors - async', async () => {
560 let err;
561 try {
@@ -551,6 +571,7 @@ function runActTests(label, render, unmount, rerender) {
571 }
572 });
573
574 + // @gate __DEV__
575 it('should cleanup after errors - sync', () => {
576 function App() {
577 React.useEffect(() => {
@@ -576,6 +597,7 @@ function runActTests(label, render, unmount, rerender) {
597 }
598 });
599
600 + // @gate __DEV__
601 it('should cleanup after errors - async', async () => {
602 function App() {
603 async function somethingAsync() {
@@ -611,6 +633,7 @@ function runActTests(label, render, unmount, rerender) {
633 if (__DEV__ && __EXPERIMENTAL__) {
634 // todo - remove __DEV__ check once we start using testing builds
635
636 + // @gate __DEV__
637 it('triggers fallbacks if available', async () => {
638 if (label !== 'legacy mode') {
639 // FIXME: Support for Concurrent Root intentionally removed
@@ -691,25 +714,12 @@ function runActTests(label, render, unmount, rerender) {
714 });
715 }
716 });
694 - describe('warn in prod mode', () => {
717 + describe('throw in prod mode', () => {
718 + // @gate !__DEV__
719 it('warns if you try to use act() in prod mode', () => {
696 - const spy = spyOnDevAndProd(console, 'error');
697 -
698 - act(() => {});
699 -
700 - if (!__DEV__) {
701 - expect(console.error).toHaveBeenCalledTimes(1);
702 - expect(console.error.calls.argsFor(0)[0]).toContain(
703 - 'act(...) is not supported in production builds of React',
704 - );
705 - } else {
706 - expect(console.error).toHaveBeenCalledTimes(0);
707 - }
708 -
709 - spy.calls.reset();
710 - // does not warn twice
711 - act(() => {});
712 - expect(console.error).toHaveBeenCalledTimes(0);
720 + expect(() => act(() => {})).toThrow(
721 + 'act(...) is not supported in production builds of React',
722 + );
723 });
724 });
725 });
packages/react-dom/src/__tests__/ReactTestUtilsActUnmockedScheduler-test.js
+5
@@ -47,6 +47,7 @@ afterEach(() => {
47 document.body.removeChild(container);
48 });
49
50 +// @gate __DEV__
51 it('can use act to flush effects', () => {
52 function App() {
53 React.useEffect(() => {
@@ -62,6 +63,7 @@ it('can use act to flush effects', () => {
63 expect(clearYields()).toEqual([100]);
64 });
65
66 +// @gate __DEV__
67 it('flushes effects on every call', () => {
68 function App() {
69 const [ctr, setCtr] = React.useState(0);
@@ -100,6 +102,7 @@ it('flushes effects on every call', () => {
102 expect(button.innerHTML).toEqual('5');
103 });
104
105 +// @gate __DEV__
106 it("should keep flushing effects until they're done", () => {
107 function App() {
108 const [ctr, setCtr] = React.useState(0);
@@ -118,6 +121,7 @@ it("should keep flushing effects until they're done", () => {
121 expect(container.innerHTML).toEqual('5');
122 });
123
124 +// @gate __DEV__
125 it('should flush effects only on exiting the outermost act', () => {
126 function App() {
127 React.useEffect(() => {
@@ -138,6 +142,7 @@ it('should flush effects only on exiting the outermost act', () => {
142 expect(clearYields()).toEqual([0]);
143 });
144
145 +// @gate __DEV__
146 it('can handle cascading promises', async () => {
147 // this component triggers an effect, that waits a tick,
148 // then sets state. repeats this 5 times.
packages/react-dom/src/test-utils/ReactTestUtilsPublicAct.js
+5 -8
@@ -13,6 +13,7 @@ import * as ReactDOM from 'react-dom';
13 import ReactSharedInternals from 'shared/ReactSharedInternals';
14 import enqueueTask from 'shared/enqueueTask';
15 import * as Scheduler from 'scheduler';
16 +import invariant from 'shared/invariant';
17
18 // Keep in sync with ReactDOM.js, and ReactTestUtils.js:
19 const EventInternals =
@@ -71,17 +72,13 @@ function flushWorkAndMicroTasks(onDone: (err: ?Error) => void) {
72 // so we can tell if any async act() calls try to run in parallel.
73
74 let actingUpdatesScopeDepth = 0;
74 -let didWarnAboutUsingActInProd = false;
75
76 export function act(callback: () => Thenable<mixed>): Thenable<void> {
77 if (!__DEV__) {
78 - if (didWarnAboutUsingActInProd === false) {
79 - didWarnAboutUsingActInProd = true;
80 - // eslint-disable-next-line react-internal/no-production-logging
81 - console.error(
82 - 'act(...) is not supported in production builds of React, and might not behave as expected.',
83 - );
84 - }
78 + invariant(
79 + false,
80 + 'act(...) is not supported in production builds of React.',
81 + );
82 }
83 const previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;
84 actingUpdatesScopeDepth++;
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+4 -8
@@ -2985,17 +2985,13 @@ function flushWorkAndMicroTasks(onDone: (err: ?Error) => void) {
2985 // so we can tell if any async act() calls try to run in parallel.
2986
2987 let actingUpdatesScopeDepth = 0;
2988 -let didWarnAboutUsingActInProd = false;
2988
2989 export function act(callback: () => Thenable<mixed>): Thenable<void> {
2990 if (!__DEV__) {
2992 - if (didWarnAboutUsingActInProd === false) {
2993 - didWarnAboutUsingActInProd = true;
2994 - // eslint-disable-next-line react-internal/no-production-logging
2995 - console.error(
2996 - 'act(...) is not supported in production builds of React, and might not behave as expected.',
2997 - );
2998 - }
2991 + invariant(
2992 + false,
2993 + 'act(...) is not supported in production builds of React.',
2994 + );
2995 }
2996
2997 const previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+4 -8
@@ -2985,17 +2985,13 @@ function flushWorkAndMicroTasks(onDone: (err: ?Error) => void) {
2985 // so we can tell if any async act() calls try to run in parallel.
2986
2987 let actingUpdatesScopeDepth = 0;
2988 -let didWarnAboutUsingActInProd = false;
2988
2989 export function act(callback: () => Thenable<mixed>): Thenable<void> {
2990 if (!__DEV__) {
2992 - if (didWarnAboutUsingActInProd === false) {
2993 - didWarnAboutUsingActInProd = true;
2994 - // eslint-disable-next-line react-internal/no-production-logging
2995 - console.error(
2996 - 'act(...) is not supported in production builds of React, and might not behave as expected.',
2997 - );
2998 - }
2991 + invariant(
2992 + false,
2993 + 'act(...) is not supported in production builds of React.',
2994 + );
2995 }
2996
2997 const previousActingUpdatesScopeDepth = actingUpdatesScopeDepth;
packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js
+2
@@ -26,6 +26,7 @@ describe('ReactFiberHostContext', () => {
26 .DefaultEventPriority;
27 });
28
29 + // @gate __DEV__
30 it('works with null host context', async () => {
31 let creates = 0;
32 const Renderer = ReactFiberReconciler({
@@ -83,6 +84,7 @@ describe('ReactFiberHostContext', () => {
84 expect(creates).toBe(2);
85 });
86
87 + // @gate __DEV__
88 it('should send the context to prepareForCommit and resetAfterCommit', () => {
89 const rootContext = {};
90 const Renderer = ReactFiberReconciler({
packages/react-reconciler/src/__tests__/ReactUpdaters-test.internal.js
+19 -16
@@ -18,6 +18,7 @@ let mockDevToolsHook;
18 let allSchedulerTags;
19 let allSchedulerTypes;
20 let onCommitRootShouldYield;
21 +let act;
22
23 describe('updaters', () => {
24 beforeEach(() => {
@@ -66,6 +67,8 @@ describe('updaters', () => {
67 ReactDOM = require('react-dom');
68 ReactTestUtils = require('react-dom/test-utils');
69 Scheduler = require('scheduler');
70 +
71 + act = ReactTestUtils.unstable_concurrentAct;
72 });
73
74 it('should report the (host) root as the scheduler for root-level render', async () => {
@@ -75,12 +78,12 @@ describe('updaters', () => {
78 const Child = () => null;
79 const container = document.createElement('div');
80
78 - await ReactTestUtils.act(async () => {
81 + await act(async () => {
82 ReactDOM.render(<Parent />, container);
83 });
84 expect(allSchedulerTags).toEqual([[HostRoot]]);
85
83 - await ReactTestUtils.act(async () => {
86 + await act(async () => {
87 ReactDOM.render(<Parent />, container);
88 });
89 expect(allSchedulerTags).toEqual([[HostRoot], [HostRoot]]);
@@ -108,19 +111,19 @@ describe('updaters', () => {
111 };
112 const Child = () => null;
113
111 - await ReactTestUtils.act(async () => {
114 + await act(async () => {
115 ReactDOM.render(<Parent />, document.createElement('div'));
116 });
117 expect(scheduleForA).not.toBeNull();
118 expect(scheduleForB).not.toBeNull();
119 expect(allSchedulerTypes).toEqual([[null]]);
120
118 - await ReactTestUtils.act(async () => {
121 + await act(async () => {
122 scheduleForA();
123 });
124 expect(allSchedulerTypes).toEqual([[null], [SchedulingComponentA]]);
125
123 - await ReactTestUtils.act(async () => {
126 + await act(async () => {
127 scheduleForB();
128 });
129 expect(allSchedulerTypes).toEqual([
@@ -141,13 +144,13 @@ describe('updaters', () => {
144 }
145 const Child = () => null;
146 let instance;
144 - await ReactTestUtils.act(async () => {
147 + await act(async () => {
148 ReactDOM.render(<Parent />, document.createElement('div'));
149 });
150 expect(allSchedulerTypes).toEqual([[null]]);
151
152 expect(instance).not.toBeNull();
150 - await ReactTestUtils.act(async () => {
153 + await act(async () => {
154 instance.setState({});
155 });
156 expect(allSchedulerTypes).toEqual([[null], [SchedulingComponent]]);
@@ -183,7 +186,7 @@ describe('updaters', () => {
186 };
187
188 const root = ReactDOM.createRoot(document.createElement('div'));
186 - await ReactTestUtils.act(async () => {
189 + await act(async () => {
190 root.render(<Parent />);
191 expect(Scheduler).toFlushAndYieldThrough([
192 'CascadingChild 0',
@@ -194,7 +197,7 @@ describe('updaters', () => {
197 expect(triggerPassiveCascade).not.toBeNull();
198 expect(allSchedulerTypes).toEqual([[null]]);
199
197 - await ReactTestUtils.act(async () => {
200 + await act(async () => {
201 triggerActiveCascade();
202 expect(Scheduler).toFlushAndYieldThrough([
203 'CascadingChild 0',
@@ -209,7 +212,7 @@ describe('updaters', () => {
212 [CascadingChild],
213 ]);
214
212 - await ReactTestUtils.act(async () => {
215 + await act(async () => {
216 triggerPassiveCascade();
217 expect(Scheduler).toFlushAndYieldThrough([
218 'CascadingChild 1',
@@ -264,21 +267,21 @@ describe('updaters', () => {
267 }
268 };
269
267 - await ReactTestUtils.act(async () => {
270 + await act(async () => {
271 ReactDOM.render(<Parent />, document.createElement('div'));
272 expect(Scheduler).toHaveYielded(['onCommitRoot']);
273 });
274 expect(setShouldSuspend).not.toBeNull();
275 expect(allSchedulerTypes).toEqual([[null]]);
276
274 - await ReactTestUtils.act(async () => {
277 + await act(async () => {
278 setShouldSuspend(true);
279 });
280 expect(Scheduler).toHaveYielded(['onCommitRoot']);
281 expect(allSchedulerTypes).toEqual([[null], [Suspender]]);
282
283 expect(resolver).not.toBeNull();
281 - await ReactTestUtils.act(() => {
284 + await act(() => {
285 resolver('abc');
286 return promise;
287 });
@@ -328,7 +331,7 @@ describe('updaters', () => {
331 };
332
333 const root = ReactDOM.createRoot(document.createElement('div'));
331 - await ReactTestUtils.act(async () => {
334 + await act(async () => {
335 root.render(<Parent shouldError={false} />);
336 });
337 expect(Scheduler).toHaveYielded(['initial', 'onCommitRoot']);
@@ -337,7 +340,7 @@ describe('updaters', () => {
340 allSchedulerTypes.splice(0);
341 onCommitRootShouldYield = true;
342
340 - await ReactTestUtils.act(async () => {
343 + await act(async () => {
344 triggerError();
345 });
346 expect(Scheduler).toHaveYielded(['onCommitRoot', 'error', 'onCommitRoot']);
@@ -398,7 +401,7 @@ describe('updaters', () => {
401 expect(allSchedulerTags).toEqual([[HostRoot]]);
402
403 // Render a partial update, but don't finish.
401 - ReactTestUtils.act(() => {
404 + act(() => {
405 triggerLowPriorityUpdate();
406 expect(Scheduler).toFlushAndYieldThrough(['LowPriorityUpdater 1']);
407 expect(allSchedulerTags).toEqual([[HostRoot]]);
packages/react-test-renderer/src/__tests__/ReactTestRendererAct-test.js
+4
@@ -13,6 +13,8 @@ describe('ReactTestRenderer.act()', () => {
13 Scheduler = require('scheduler');
14 act = ReactTestRenderer.act;
15 });
16 +
17 + // @gate __DEV__
18 it('can use .act() to flush effects', () => {
19 function App(props) {
20 const [ctr, setCtr] = React.useState(0);
@@ -56,6 +58,7 @@ describe('ReactTestRenderer.act()', () => {
58 });
59
60 describe('async', () => {
61 + // @gate __DEV__
62 it('should work with async/await', async () => {
63 function fetch(url) {
64 return Promise.resolve({
@@ -83,6 +86,7 @@ describe('ReactTestRenderer.act()', () => {
86 expect(root.toJSON()).toEqual(['1', '2', '3']);
87 });
88
89 + // @gate __DEV__
90 it('should not flush effects without also flushing microtasks', async () => {
91 const {useEffect, useReducer} = React;
92
packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee
+1 -1
@@ -20,7 +20,7 @@ describe 'ReactCoffeeScriptClass', ->
20 beforeEach ->
21 React = require 'react'
22 ReactDOM = require 'react-dom'
23 - act = require('react-dom/test-utils').act
23 + act = require('react-dom/test-utils').unstable_concurrentAct
24 PropTypes = require 'prop-types'
25 container = document.createElement 'div'
26 root = ReactDOM.createRoot container
packages/react/src/__tests__/ReactES6Class-test.js
+1 -1
@@ -29,7 +29,7 @@ describe('ReactES6Class', () => {
29 PropTypes = require('prop-types');
30 React = require('react');
31 ReactDOM = require('react-dom');
32 - act = require('react-dom/test-utils').act;
32 + act = require('react-dom/test-utils').unstable_concurrentAct;
33 container = document.createElement('div');
34 root = ReactDOM.createRoot(container);
35 attachedListener = null;
packages/react/src/__tests__/ReactTypeScriptClass-test.ts
+11 -10
@@ -21,6 +21,7 @@ let container;
21 let root;
22 let attachedListener = null;
23 let renderedName = null;
24 +let act = ReactDOMTestUtils.unstable_concurrentAct;
25
26 class Inner extends React.Component {
27 getName() {
@@ -34,7 +35,7 @@ class Inner extends React.Component {
35 }
36
37 function test(element, expectedTag, expectedClassName) {
37 - ReactDOMTestUtils.act(() => root.render(element));
38 + act(() => root.render(element));
39 expect(container.firstChild).not.toBeNull();
40 expect(container.firstChild.tagName).toBe(expectedTag);
41 expect(container.firstChild.className).toBe(expectedClassName);
@@ -327,7 +328,7 @@ describe('ReactTypeScriptClass', function() {
328 it('throws if no render function is defined', function() {
329 expect(() => {
330 expect(() =>
330 - ReactDOMTestUtils.act(() => root.render(React.createElement(Empty)))
331 + act(() => root.render(React.createElement(Empty)))
332 ).toThrow();
333 }).toErrorDev([
334 // A failed component renders four times in DEV in concurrent mode
@@ -362,7 +363,7 @@ describe('ReactTypeScriptClass', function() {
363 'DIV',
364 'foo'
365 );
365 - ReactDOMTestUtils.act(() => ref.current.changeState());
366 + act(() => ref.current.changeState());
367 test(React.createElement(StateBasedOnProps), 'SPAN', 'bar');
368 });
369
@@ -397,7 +398,7 @@ describe('ReactTypeScriptClass', function() {
398 }
399 }
400 expect(function() {
400 - ReactDOMTestUtils.act(() =>
401 + act(() =>
402 root.render(React.createElement(Foo, {foo: 'foo'}))
403 );
404 }).toErrorDev(
@@ -416,7 +417,7 @@ describe('ReactTypeScriptClass', function() {
417 }
418 }
419 expect(function() {
419 - ReactDOMTestUtils.act(() =>
420 + act(() =>
421 root.render(React.createElement(Foo, {foo: 'foo'}))
422 );
423 }).toErrorDev(
@@ -433,7 +434,7 @@ describe('ReactTypeScriptClass', function() {
434 }
435 }
436 expect(function() {
436 - ReactDOMTestUtils.act(() =>
437 + act(() =>
438 root.render(React.createElement(Foo, {foo: 'foo'}))
439 );
440 }).toErrorDev(
@@ -457,7 +458,7 @@ describe('ReactTypeScriptClass', function() {
458 }
459 }
460 expect(function() {
460 - ReactDOMTestUtils.act(() =>
461 + act(() =>
462 root.render(React.createElement(Foo, {foo: 'foo'}))
463 );
464 }).toErrorDev(
@@ -543,7 +544,7 @@ describe('ReactTypeScriptClass', function() {
544 'DIV',
545 'foo'
546 );
546 - ReactDOMTestUtils.act(() => attachedListener());
547 + act(() => attachedListener());
548 expect(renderedName).toBe('bar');
549 });
550
@@ -562,7 +563,7 @@ describe('ReactTypeScriptClass', function() {
563 'DIV',
564 'foo'
565 );
565 - ReactDOMTestUtils.act(() => attachedListener());
566 + act(() => attachedListener());
567 expect(renderedName).toBe('bar');
568 });
569
@@ -586,7 +587,7 @@ describe('ReactTypeScriptClass', function() {
587 {},
588 ]);
589 lifeCycles = []; // reset
589 - ReactDOMTestUtils.act(() => root.unmount(container));
590 + act(() => root.unmount(container));
591 expect(lifeCycles).toEqual(['will-unmount']);
592 });
593
packages/react/src/__tests__/testDefinitions/ReactDOMTestUtils.d.ts
+1 -1
@@ -13,5 +13,5 @@
13 */
14
15 declare module 'react-dom/test-utils' {
16 - export function act(cb : () => any) : any
16 + export function unstable_concurrentAct(cb : () => any) : any
17 }
scripts/error-codes/codes.json
+2 -1
@@ -393,5 +393,6 @@
393 "402": "The depth must equal at least at zero before reaching the root. This is a bug in React.",
394 "403": "Tried to pop a Context at the root of the app. This is a bug in React.",
395 "404": "Invalid hook call. Hooks can only be called inside of the body of a function component.",
396 - "405": "hydrateRoot(...): Target container is not a DOM element."
396 + "405": "hydrateRoot(...): Target container is not a DOM element.",
397 + "406": "act(...) is not supported in production builds of React."
398 }
scripts/jest/shouldIgnoreConsoleError.js
-10
@@ -35,16 +35,6 @@ module.exports = function shouldIgnoreConsoleError(format, args) {
35 // They are noisy too so we'll try to ignore them.
36 return true;
37 }
38 - if (
39 - format.indexOf(
40 - 'act(...) is not supported in production builds of React'
41 - ) === 0
42 - ) {
43 - // We don't yet support act() for prod builds, and warn for it.
44 - // But we'd like to use act() ourselves for prod builds.
45 - // Let's ignore the warning and #yolo.
46 - return true;
47 - }
38 }
39 // Looks legit
40 return false;