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;