Codemod act -> await act (3/?) (#26336)
Similar to the rationale for `waitFor` (see #26285), we should always await the result of an `act` call so that microtasks have a chance to fire. This only affects the internal `act` that we use in our repo, for now. In the public `act` API, we don't yet require this; however, we effectively will for any update that triggers suspense once `use` lands. So we likely will start warning in an upcoming minor.
Andrew Clark committed
Mar 7, 2023 at 14:39 UTC
161f6ae42cf570d3daec355abcf3b006c58315da
11 files changed
+179
-163
packages/react-reconciler/src/__tests__/StrictEffectsMode-test.js
+35
-35
@@ -36,7 +36,7 @@ describe('StrictEffectsMode', () => {
36
);
37
}
38
39
- it('should not double invoke effects in legacy mode', () => {
39
+ it('should not double invoke effects in legacy mode', async () => {
40
function App({text}) {
41
React.useEffect(() => {
42
Scheduler.log('useEffect mount');
@@ -51,14 +51,14 @@ describe('StrictEffectsMode', () => {
51
return text;
52
}
53
54
- act(() => {
54
+ await act(async () => {
55
ReactTestRenderer.create(<App text={'mount'} />);
56
});
57
58
assertLog(['useLayoutEffect mount', 'useEffect mount']);
59
});
60
61
- it('double invoking for effects works properly', () => {
61
+ it('double invoking for effects works properly', async () => {
62
function App({text}) {
63
React.useEffect(() => {
64
Scheduler.log('useEffect mount');
@@ -74,7 +74,7 @@ describe('StrictEffectsMode', () => {
74
}
75
76
let renderer;
77
- act(() => {
77
+ await act(async () => {
78
renderer = ReactTestRenderer.create(<App text={'mount'} />, {
79
unstable_isConcurrent: true,
80
});
@@ -93,7 +93,7 @@ describe('StrictEffectsMode', () => {
93
assertLog(['useLayoutEffect mount', 'useEffect mount']);
94
}
95
96
- act(() => {
96
+ await act(async () => {
97
renderer.update(<App text={'update'} />);
98
});
99
@@ -104,14 +104,14 @@ describe('StrictEffectsMode', () => {
104
'useEffect mount',
105
]);
106
107
- act(() => {
107
+ await act(async () => {
108
renderer.unmount();
109
});
110
111
assertLog(['useLayoutEffect unmount', 'useEffect unmount']);
112
});
113
114
- it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
114
+ it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
115
function App({text}) {
116
React.useEffect(() => {
117
Scheduler.log('useEffect One mount');
@@ -127,7 +127,7 @@ describe('StrictEffectsMode', () => {
127
}
128
129
let renderer;
130
- act(() => {
130
+ await act(async () => {
131
renderer = ReactTestRenderer.create(<App text={'mount'} />, {
132
unstable_isConcurrent: true,
133
});
@@ -146,7 +146,7 @@ describe('StrictEffectsMode', () => {
146
assertLog(['useEffect One mount', 'useEffect Two mount']);
147
}
148
149
- act(() => {
149
+ await act(async () => {
150
renderer.update(<App text={'update'} />);
151
});
152
@@ -157,14 +157,14 @@ describe('StrictEffectsMode', () => {
157
'useEffect Two mount',
158
]);
159
160
- act(() => {
160
+ await act(async () => {
161
renderer.unmount(null);
162
});
163
164
assertLog(['useEffect One unmount', 'useEffect Two unmount']);
165
});
166
167
- it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
167
+ it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
168
function App({text}) {
169
React.useLayoutEffect(() => {
170
Scheduler.log('useLayoutEffect One mount');
@@ -180,7 +180,7 @@ describe('StrictEffectsMode', () => {
180
}
181
182
let renderer;
183
- act(() => {
183
+ await act(async () => {
184
renderer = ReactTestRenderer.create(<App text={'mount'} />, {
185
unstable_isConcurrent: true,
186
});
@@ -199,7 +199,7 @@ describe('StrictEffectsMode', () => {
199
assertLog(['useLayoutEffect One mount', 'useLayoutEffect Two mount']);
200
}
201
202
- act(() => {
202
+ await act(async () => {
203
renderer.update(<App text={'update'} />);
204
});
205
@@ -210,14 +210,14 @@ describe('StrictEffectsMode', () => {
210
'useLayoutEffect Two mount',
211
]);
212
213
- act(() => {
213
+ await act(async () => {
214
renderer.unmount();
215
});
216
217
assertLog(['useLayoutEffect One unmount', 'useLayoutEffect Two unmount']);
218
});
219
220
- it('useEffect and useLayoutEffect is called twice when there is no unmount', () => {
220
+ it('useEffect and useLayoutEffect is called twice when there is no unmount', async () => {
221
function App({text}) {
222
React.useEffect(() => {
223
Scheduler.log('useEffect mount');
@@ -231,7 +231,7 @@ describe('StrictEffectsMode', () => {
231
}
232
233
let renderer;
234
- act(() => {
234
+ await act(async () => {
235
renderer = ReactTestRenderer.create(<App text={'mount'} />, {
236
unstable_isConcurrent: true,
237
});
@@ -248,20 +248,20 @@ describe('StrictEffectsMode', () => {
248
assertLog(['useLayoutEffect mount', 'useEffect mount']);
249
}
250
251
- act(() => {
251
+ await act(async () => {
252
renderer.update(<App text={'update'} />);
253
});
254
255
assertLog(['useLayoutEffect mount', 'useEffect mount']);
256
257
- act(() => {
257
+ await act(async () => {
258
renderer.unmount();
259
});
260
261
assertLog([]);
262
});
263
264
- it('passes the right context to class component lifecycles', () => {
264
+ it('passes the right context to class component lifecycles', async () => {
265
class App extends React.PureComponent {
266
test() {}
267
@@ -285,7 +285,7 @@ describe('StrictEffectsMode', () => {
285
}
286
}
287
288
- act(() => {
288
+ await act(async () => {
289
ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});
290
});
291
@@ -300,7 +300,7 @@ describe('StrictEffectsMode', () => {
300
}
301
});
302
303
- it('double invoking works for class components', () => {
303
+ it('double invoking works for class components', async () => {
304
class App extends React.PureComponent {
305
componentDidMount() {
306
Scheduler.log('componentDidMount');
@@ -320,7 +320,7 @@ describe('StrictEffectsMode', () => {
320
}
321
322
let renderer;
323
- act(() => {
323
+ await act(async () => {
324
renderer = ReactTestRenderer.create(<App text={'mount'} />, {
325
unstable_isConcurrent: true,
326
});
@@ -336,20 +336,20 @@ describe('StrictEffectsMode', () => {
336
assertLog(['componentDidMount']);
337
}
338
339
- act(() => {
339
+ await act(async () => {
340
renderer.update(<App text={'update'} />);
341
});
342
343
assertLog(['componentDidUpdate']);
344
345
- act(() => {
345
+ await act(async () => {
346
renderer.unmount();
347
});
348
349
assertLog(['componentWillUnmount']);
350
});
351
352
- it('should not double invoke class lifecycles in legacy mode', () => {
352
+ it('should not double invoke class lifecycles in legacy mode', async () => {
353
class App extends React.PureComponent {
354
componentDidMount() {
355
Scheduler.log('componentDidMount');
@@ -368,14 +368,14 @@ describe('StrictEffectsMode', () => {
368
}
369
}
370
371
- act(() => {
371
+ await act(async () => {
372
ReactTestRenderer.create(<App text={'mount'} />);
373
});
374
375
assertLog(['componentDidMount']);
376
});
377
378
- it('double flushing passive effects only results in one double invoke', () => {
378
+ it('double flushing passive effects only results in one double invoke', async () => {
379
function App({text}) {
380
const [state, setState] = React.useState(0);
381
React.useEffect(() => {
@@ -395,7 +395,7 @@ describe('StrictEffectsMode', () => {
395
return text;
396
}
397
398
- act(() => {
398
+ await act(async () => {
399
ReactTestRenderer.create(<App text={'mount'} />, {
400
unstable_isConcurrent: true,
401
});
@@ -430,7 +430,7 @@ describe('StrictEffectsMode', () => {
430
}
431
});
432
433
- it('newly mounted components after initial mount get double invoked', () => {
433
+ it('newly mounted components after initial mount get double invoked', async () => {
434
let _setShowChild;
435
function Child() {
436
React.useEffect(() => {
@@ -460,7 +460,7 @@ describe('StrictEffectsMode', () => {
460
return showChild && <Child />;
461
}
462
463
- act(() => {
463
+ await act(async () => {
464
ReactTestRenderer.create(<App />, {unstable_isConcurrent: true});
465
});
466
@@ -477,7 +477,7 @@ describe('StrictEffectsMode', () => {
477
assertLog(['App useLayoutEffect mount', 'App useEffect mount']);
478
}
479
480
- act(() => {
480
+ await act(async () => {
481
_setShowChild(true);
482
});
483
@@ -506,7 +506,7 @@ describe('StrictEffectsMode', () => {
506
}
507
});
508
509
- it('classes and functions are double invoked together correctly', () => {
509
+ it('classes and functions are double invoked together correctly', async () => {
510
class ClassChild extends React.PureComponent {
511
componentDidMount() {
512
Scheduler.log('componentDidMount');
@@ -543,7 +543,7 @@ describe('StrictEffectsMode', () => {
543
}
544
545
let renderer;
546
- act(() => {
546
+ await act(async () => {
547
renderer = ReactTestRenderer.create(<App text={'mount'} />, {
548
unstable_isConcurrent: true,
549
});
@@ -569,7 +569,7 @@ describe('StrictEffectsMode', () => {
569
]);
570
}
571
572
- act(() => {
572
+ await act(async () => {
573
renderer.update(<App text={'mount'} />);
574
});
575
@@ -580,7 +580,7 @@ describe('StrictEffectsMode', () => {
580
'useEffect mount',
581
]);
582
583
- act(() => {
583
+ await act(async () => {
584
renderer.unmount();
585
});
586
packages/react-reconciler/src/__tests__/StrictEffectsModeDefaults-test.internal.js
+37
-37
@@ -37,7 +37,7 @@ describe('StrictEffectsMode defaults', () => {
37
ReactFeatureFlags.createRootStrictEffectsByDefault = __DEV__;
38
});
39
40
- it('should not double invoke effects in legacy mode', () => {
40
+ it('should not double invoke effects in legacy mode', async () => {
41
function App({text}) {
42
React.useEffect(() => {
43
Scheduler.log('useEffect mount');
@@ -52,14 +52,14 @@ describe('StrictEffectsMode defaults', () => {
52
return text;
53
}
54
55
- act(() => {
55
+ await act(async () => {
56
ReactNoop.renderLegacySyncRoot(<App text={'mount'} />);
57
});
58
59
assertLog(['useLayoutEffect mount', 'useEffect mount']);
60
});
61
62
- it('should not double invoke class lifecycles in legacy mode', () => {
62
+ it('should not double invoke class lifecycles in legacy mode', async () => {
63
class App extends React.PureComponent {
64
componentDidMount() {
65
Scheduler.log('componentDidMount');
@@ -78,7 +78,7 @@ describe('StrictEffectsMode defaults', () => {
78
}
79
}
80
81
- act(() => {
81
+ await act(async () => {
82
ReactNoop.renderLegacySyncRoot(<App text={'mount'} />);
83
});
84
@@ -194,7 +194,7 @@ describe('StrictEffectsMode defaults', () => {
194
});
195
});
196
197
- it('double invoking for effects for modern roots', () => {
197
+ it('double invoking for effects for modern roots', async () => {
198
function App({text}) {
199
React.useEffect(() => {
200
Scheduler.log('useEffect mount');
@@ -208,7 +208,7 @@ describe('StrictEffectsMode defaults', () => {
208
209
return text;
210
}
211
- act(() => {
211
+ await act(async () => {
212
ReactNoop.render(<App text={'mount'} />);
213
});
214
@@ -221,7 +221,7 @@ describe('StrictEffectsMode defaults', () => {
221
'useEffect mount',
222
]);
223
224
- act(() => {
224
+ await act(async () => {
225
ReactNoop.render(<App text={'update'} />);
226
});
227
@@ -232,14 +232,14 @@ describe('StrictEffectsMode defaults', () => {
232
'useEffect mount',
233
]);
234
235
- act(() => {
235
+ await act(async () => {
236
ReactNoop.render(null);
237
});
238
239
assertLog(['useLayoutEffect unmount', 'useEffect unmount']);
240
});
241
242
- it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
242
+ it('multiple effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
243
function App({text}) {
244
React.useEffect(() => {
245
Scheduler.log('useEffect One mount');
@@ -254,7 +254,7 @@ describe('StrictEffectsMode defaults', () => {
254
return text;
255
}
256
257
- act(() => {
257
+ await act(async () => {
258
ReactNoop.render(<App text={'mount'} />);
259
});
260
@@ -267,7 +267,7 @@ describe('StrictEffectsMode defaults', () => {
267
'useEffect Two mount',
268
]);
269
270
- act(() => {
270
+ await act(async () => {
271
ReactNoop.render(<App text={'update'} />);
272
});
273
@@ -278,14 +278,14 @@ describe('StrictEffectsMode defaults', () => {
278
'useEffect Two mount',
279
]);
280
281
- act(() => {
281
+ await act(async () => {
282
ReactNoop.render(null);
283
});
284
285
assertLog(['useEffect One unmount', 'useEffect Two unmount']);
286
});
287
288
- it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', () => {
288
+ it('multiple layout effects are double invoked in the right order (all mounted, all unmounted, all remounted)', async () => {
289
function App({text}) {
290
React.useLayoutEffect(() => {
291
Scheduler.log('useLayoutEffect One mount');
@@ -300,7 +300,7 @@ describe('StrictEffectsMode defaults', () => {
300
return text;
301
}
302
303
- act(() => {
303
+ await act(async () => {
304
ReactNoop.render(<App text={'mount'} />);
305
});
306
@@ -313,7 +313,7 @@ describe('StrictEffectsMode defaults', () => {
313
'useLayoutEffect Two mount',
314
]);
315
316
- act(() => {
316
+ await act(async () => {
317
ReactNoop.render(<App text={'update'} />);
318
});
319
@@ -324,14 +324,14 @@ describe('StrictEffectsMode defaults', () => {
324
'useLayoutEffect Two mount',
325
]);
326
327
- act(() => {
327
+ await act(async () => {
328
ReactNoop.render(null);
329
});
330
331
assertLog(['useLayoutEffect One unmount', 'useLayoutEffect Two unmount']);
332
});
333
334
- it('useEffect and useLayoutEffect is called twice when there is no unmount', () => {
334
+ it('useEffect and useLayoutEffect is called twice when there is no unmount', async () => {
335
function App({text}) {
336
React.useEffect(() => {
337
Scheduler.log('useEffect mount');
@@ -344,7 +344,7 @@ describe('StrictEffectsMode defaults', () => {
344
return text;
345
}
346
347
- act(() => {
347
+ await act(async () => {
348
ReactNoop.render(<App text={'mount'} />);
349
});
350
@@ -355,13 +355,13 @@ describe('StrictEffectsMode defaults', () => {
355
'useEffect mount',
356
]);
357
358
- act(() => {
358
+ await act(async () => {
359
ReactNoop.render(<App text={'update'} />);
360
});
361
362
assertLog(['useLayoutEffect mount', 'useEffect mount']);
363
364
- act(() => {
364
+ await act(async () => {
365
ReactNoop.render(null);
366
});
367
@@ -369,7 +369,7 @@ describe('StrictEffectsMode defaults', () => {
369
});
370
371
//@gate useModernStrictMode
372
- it('disconnects refs during double invoking', () => {
372
+ it('disconnects refs during double invoking', async () => {
373
const onRefMock = jest.fn();
374
function App({text}) {
375
return (
@@ -382,7 +382,7 @@ describe('StrictEffectsMode defaults', () => {
382
);
383
}
384
385
- act(() => {
385
+ await act(async () => {
386
ReactNoop.render(<App text={'mount'} />);
387
});
388
@@ -392,7 +392,7 @@ describe('StrictEffectsMode defaults', () => {
392
expect(onRefMock.mock.calls[2][0]).not.toBeNull();
393
});
394
395
- it('passes the right context to class component lifecycles', () => {
395
+ it('passes the right context to class component lifecycles', async () => {
396
class App extends React.PureComponent {
397
test() {}
398
@@ -416,7 +416,7 @@ describe('StrictEffectsMode defaults', () => {
416
}
417
}
418
419
- act(() => {
419
+ await act(async () => {
420
ReactNoop.render(<App />);
421
});
422
@@ -427,7 +427,7 @@ describe('StrictEffectsMode defaults', () => {
427
]);
428
});
429
430
- it('double invoking works for class components', () => {
430
+ it('double invoking works for class components', async () => {
431
class App extends React.PureComponent {
432
componentDidMount() {
433
Scheduler.log('componentDidMount');
@@ -446,7 +446,7 @@ describe('StrictEffectsMode defaults', () => {
446
}
447
}
448
449
- act(() => {
449
+ await act(async () => {
450
ReactNoop.render(<App text={'mount'} />);
451
});
452
@@ -456,20 +456,20 @@ describe('StrictEffectsMode defaults', () => {
456
'componentDidMount',
457
]);
458
459
- act(() => {
459
+ await act(async () => {
460
ReactNoop.render(<App text={'update'} />);
461
});
462
463
assertLog(['componentDidUpdate']);
464
465
- act(() => {
465
+ await act(async () => {
466
ReactNoop.render(null);
467
});
468
469
assertLog(['componentWillUnmount']);
470
});
471
472
- it('double flushing passive effects only results in one double invoke', () => {
472
+ it('double flushing passive effects only results in one double invoke', async () => {
473
function App({text}) {
474
const [state, setState] = React.useState(0);
475
React.useEffect(() => {
@@ -489,7 +489,7 @@ describe('StrictEffectsMode defaults', () => {
489
return text;
490
}
491
492
- act(() => {
492
+ await act(async () => {
493
ReactNoop.render(<App text={'mount'} />);
494
});
495
@@ -509,7 +509,7 @@ describe('StrictEffectsMode defaults', () => {
509
]);
510
});
511
512
- it('newly mounted components after initial mount get double invoked', () => {
512
+ it('newly mounted components after initial mount get double invoked', async () => {
513
let _setShowChild;
514
function Child() {
515
React.useEffect(() => {
@@ -539,7 +539,7 @@ describe('StrictEffectsMode defaults', () => {
539
return showChild && <Child />;
540
}
541
542
- act(() => {
542
+ await act(async () => {
543
ReactNoop.render(<App />);
544
});
545
@@ -552,7 +552,7 @@ describe('StrictEffectsMode defaults', () => {
552
'App useEffect mount',
553
]);
554
555
- act(() => {
555
+ await act(async () => {
556
_setShowChild(true);
557
});
558
@@ -570,7 +570,7 @@ describe('StrictEffectsMode defaults', () => {
570
]);
571
});
572
573
- it('classes and functions are double invoked together correctly', () => {
573
+ it('classes and functions are double invoked together correctly', async () => {
574
class ClassChild extends React.PureComponent {
575
componentDidMount() {
576
Scheduler.log('componentDidMount');
@@ -606,7 +606,7 @@ describe('StrictEffectsMode defaults', () => {
606
);
607
}
608
609
- act(() => {
609
+ await act(async () => {
610
ReactNoop.render(<App text={'mount'} />);
611
});
612
@@ -622,7 +622,7 @@ describe('StrictEffectsMode defaults', () => {
622
'useEffect mount',
623
]);
624
625
- act(() => {
625
+ await act(async () => {
626
ReactNoop.render(<App text={'mount'} />);
627
});
628
@@ -633,7 +633,7 @@ describe('StrictEffectsMode defaults', () => {
633
'useEffect mount',
634
]);
635
636
- act(() => {
636
+ await act(async () => {
637
ReactNoop.render(null);
638
});
639
packages/react-reconciler/src/__tests__/useEffectEvent-test.js
+33
-27
@@ -604,7 +604,7 @@ describe('useEffectEvent', () => {
604
ReactNoop.render(<Counter value={1} />);
605
await waitForAll(['Effect value: 1', 'Event value: 1']);
606
607
- act(() => ReactNoop.render(<Counter value={2} />));
607
+ await act(async () => ReactNoop.render(<Counter value={2} />));
608
assertLog(['Effect value: 2', 'Event value: 2']);
609
});
610
@@ -742,52 +742,58 @@ describe('useEffectEvent', () => {
742
return <Text text={`Welcome to the ${roomId} room!`} />;
743
}
744
745
- act(() => ReactNoop.render(<ChatRoom roomId="general" theme="light" />));
746
- assertLog(['Welcome to the general room!']);
745
+ await act(async () =>
746
+ ReactNoop.render(<ChatRoom roomId="general" theme="light" />),
747
+ );
748
+ await act(async () => jest.runAllTimers());
749
+ assertLog(['Welcome to the general room!', 'Connected! theme: light']);
750
expect(ReactNoop).toMatchRenderedOutput(
751
<span prop="Welcome to the general room!" />,
752
);
753
751
- jest.advanceTimersByTime(100);
752
- Scheduler.unstable_advanceTime(100);
753
- assertLog(['Connected! theme: light']);
754
-
754
// change roomId only
756
- act(() => ReactNoop.render(<ChatRoom roomId="music" theme="light" />));
757
- assertLog(['Welcome to the music room!']);
755
+ await act(async () =>
756
+ ReactNoop.render(<ChatRoom roomId="music" theme="light" />),
757
+ );
758
+ await act(async () => jest.runAllTimers());
759
+ assertLog([
760
+ 'Welcome to the music room!',
761
+ // should trigger a reconnect
762
+ 'Connected! theme: light',
763
+ ]);
764
+
765
expect(ReactNoop).toMatchRenderedOutput(
766
<span prop="Welcome to the music room!" />,
767
);
761
- jest.advanceTimersByTime(100);
762
- Scheduler.unstable_advanceTime(100);
763
- // should trigger a reconnect
764
- assertLog(['Connected! theme: light']);
768
769
// change theme only
767
- act(() => ReactNoop.render(<ChatRoom roomId="music" theme="dark" />));
770
+ await act(async () =>
771
+ ReactNoop.render(<ChatRoom roomId="music" theme="dark" />),
772
+ );
773
+ await act(async () => jest.runAllTimers());
774
+ // should not trigger a reconnect
775
assertLog(['Welcome to the music room!']);
776
expect(ReactNoop).toMatchRenderedOutput(
777
<span prop="Welcome to the music room!" />,
778
);
772
- jest.advanceTimersByTime(100);
773
- Scheduler.unstable_advanceTime(100);
774
- // should not trigger a reconnect
775
- await waitForAll([]);
779
780
// change roomId only
778
- act(() => ReactNoop.render(<ChatRoom roomId="travel" theme="dark" />));
779
- assertLog(['Welcome to the travel room!']);
781
+ await act(async () =>
782
+ ReactNoop.render(<ChatRoom roomId="travel" theme="dark" />),
783
+ );
784
+ await act(async () => jest.runAllTimers());
785
+ assertLog([
786
+ 'Welcome to the travel room!',
787
+ // should trigger a reconnect
788
+ 'Connected! theme: dark',
789
+ ]);
790
expect(ReactNoop).toMatchRenderedOutput(
791
<span prop="Welcome to the travel room!" />,
792
);
783
- jest.advanceTimersByTime(100);
784
- Scheduler.unstable_advanceTime(100);
785
- // should trigger a reconnect
786
- assertLog(['Connected! theme: dark']);
793
});
794
795
// @gate enableUseEffectEventHook
790
- it('integration: implements the docs logVisit example', () => {
796
+ it('integration: implements the docs logVisit example', async () => {
797
class AddToCartButton extends React.PureComponent {
798
addToCart = () => {
799
this.props.onClick();
@@ -835,7 +841,7 @@ describe('useEffectEvent', () => {
841
}
842
843
const button = React.createRef(null);
838
- act(() =>
844
+ await act(async () =>
845
ReactNoop.render(
846
<AppShell>
847
<Page url="/shop/1" />
@@ -846,7 +852,7 @@ describe('useEffectEvent', () => {
852
act(button.current.addToCart);
853
assertLog(['Add to cart']);
854
849
- act(() =>
855
+ await act(async () =>
856
ReactNoop.render(
857
<AppShell>
858
<Page url="/shop/2" />
packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js
+4
-4
@@ -1666,7 +1666,7 @@ describe('useMutableSource', () => {
1666
}
1667
1668
// Mount ComponentA with data version 1
1669
- act(() => {
1669
+ await act(async () => {
1670
ReactNoop.render(
1671
<React.Profiler id="root" onRender={onRender}>
1672
<ComponentA />
@@ -1703,7 +1703,7 @@ describe('useMutableSource', () => {
1703
if (__DEV__) {
1704
describe('dev warnings', () => {
1705
// @gate enableUseMutableSource
1706
- it('should warn if the subscribe function does not return an unsubscribe function', () => {
1706
+ it('should warn if the subscribe function does not return an unsubscribe function', async () => {
1707
const source = createSource('one');
1708
const mutableSource = createMutableSource(
1709
source,
@@ -1712,8 +1712,8 @@ describe('useMutableSource', () => {
1712
1713
const brokenSubscribe = () => {};
1714
1715
- expect(() => {
1716
- act(() => {
1715
+ await expect(async () => {
1716
+ await act(async () => {
1717
ReactNoop.render(
1718
<Component
1719
label="only"
packages/react-reconciler/src/__tests__/useMutableSourceHydration-test.js
+5
-5
@@ -142,7 +142,7 @@ describe('useMutableSourceHydration', () => {
142
}
143
144
// @gate enableUseMutableSource
145
- it('should render and hydrate', () => {
145
+ it('should render and hydrate', async () => {
146
const source = createSource('one');
147
const mutableSource = createMutableSource(source, param => param.version);
148
@@ -165,7 +165,7 @@ describe('useMutableSourceHydration', () => {
165
assertLog(['only:one']);
166
expect(source.listenerCount).toBe(0);
167
168
- act(() => {
168
+ await act(async () => {
169
ReactDOMClient.hydrateRoot(container, <TestComponent />, {
170
mutableSources: [mutableSource],
171
});
@@ -176,7 +176,7 @@ describe('useMutableSourceHydration', () => {
176
177
// @gate enableUseMutableSource
178
// @gate enableClientRenderFallbackOnTextMismatch
179
- it('should detect a tear before hydrating a component', () => {
179
+ it('should detect a tear before hydrating a component', async () => {
180
const source = createSource('one');
181
const mutableSource = createMutableSource(source, param => param.version);
182
@@ -199,8 +199,8 @@ describe('useMutableSourceHydration', () => {
199
assertLog(['only:one']);
200
expect(source.listenerCount).toBe(0);
201
202
- expect(() => {
203
- act(() => {
202
+ await expect(async () => {
203
+ await act(async () => {
204
ReactDOMClient.hydrateRoot(container, <TestComponent />, {
205
mutableSources: [mutableSource],
206
onRecoverableError(error) {
packages/react-reconciler/src/__tests__/useRef-test.internal.js
+23
-23
@@ -50,7 +50,7 @@ describe('useRef', () => {
50
return <span prop={props.text} />;
51
}
52
53
- it('creates a ref object initialized with the provided value', () => {
53
+ it('creates a ref object initialized with the provided value', async () => {
54
jest.useFakeTimers();
55
56
function useDebouncedCallback(callback, ms, inputs) {
@@ -82,7 +82,7 @@ describe('useRef', () => {
82
return null;
83
}
84
85
- act(() => {
85
+ await act(async () => {
86
ReactNoop.render(<App />);
87
});
88
assertLog([]);
@@ -134,7 +134,7 @@ describe('useRef', () => {
134
});
135
136
if (__DEV__) {
137
- it('should never warn when attaching to children', () => {
137
+ it('should never warn when attaching to children', async () => {
138
class Component extends React.Component {
139
render() {
140
return null;
@@ -152,16 +152,16 @@ describe('useRef', () => {
152
);
153
}
154
155
- act(() => {
155
+ await act(async () => {
156
ReactNoop.render(<Example phase="mount" />);
157
});
158
- act(() => {
158
+ await act(async () => {
159
ReactNoop.render(<Example phase="update" />);
160
});
161
});
162
163
// @gate enableUseRefAccessWarning
164
- it('should warn about reads during render', () => {
164
+ it('should warn about reads during render', async () => {
165
function Example() {
166
const ref = useRef(123);
167
let value;
@@ -173,12 +173,12 @@ describe('useRef', () => {
173
return value;
174
}
175
176
- act(() => {
176
+ await act(async () => {
177
ReactNoop.render(<Example />);
178
});
179
});
180
181
- it('should not warn about lazy init during render', () => {
181
+ it('should not warn about lazy init during render', async () => {
182
function Example() {
183
const ref1 = useRef(null);
184
const ref2 = useRef(undefined);
@@ -192,17 +192,17 @@ describe('useRef', () => {
192
return null;
193
}
194
195
- act(() => {
195
+ await act(async () => {
196
ReactNoop.render(<Example />);
197
});
198
199
// Should not warn after an update either.
200
- act(() => {
200
+ await act(async () => {
201
ReactNoop.render(<Example />);
202
});
203
});
204
205
- it('should not warn about lazy init outside of render', () => {
205
+ it('should not warn about lazy init outside of render', async () => {
206
function Example() {
207
// eslint-disable-next-line no-unused-vars
208
const [didMount, setDidMount] = useState(false);
@@ -216,13 +216,13 @@ describe('useRef', () => {
216
return null;
217
}
218
219
- act(() => {
219
+ await act(async () => {
220
ReactNoop.render(<Example />);
221
});
222
});
223
224
// @gate enableUseRefAccessWarning
225
- it('should warn about unconditional lazy init during render', () => {
225
+ it('should warn about unconditional lazy init during render', async () => {
226
function Example() {
227
const ref1 = useRef(null);
228
const ref2 = useRef(undefined);
@@ -251,19 +251,19 @@ describe('useRef', () => {
251
}
252
253
let shouldExpectWarning = true;
254
- act(() => {
254
+ await act(async () => {
255
ReactNoop.render(<Example />);
256
});
257
258
// Should not warn again on update.
259
shouldExpectWarning = false;
260
- act(() => {
260
+ await act(async () => {
261
ReactNoop.render(<Example />);
262
});
263
});
264
265
// @gate enableUseRefAccessWarning
266
- it('should warn about reads to ref after lazy init pattern', () => {
266
+ it('should warn about reads to ref after lazy init pattern', async () => {
267
function Example() {
268
const ref1 = useRef(null);
269
const ref2 = useRef(undefined);
@@ -291,13 +291,13 @@ describe('useRef', () => {
291
return value;
292
}
293
294
- act(() => {
294
+ await act(async () => {
295
ReactNoop.render(<Example />);
296
});
297
});
298
299
// @gate enableUseRefAccessWarning
300
- it('should warn about writes to ref after lazy init pattern', () => {
300
+ it('should warn about writes to ref after lazy init pattern', async () => {
301
function Example() {
302
const ref1 = useRef(null);
303
const ref2 = useRef(undefined);
@@ -323,12 +323,12 @@ describe('useRef', () => {
323
return null;
324
}
325
326
- act(() => {
326
+ await act(async () => {
327
ReactNoop.render(<Example />);
328
});
329
});
330
331
- it('should not warn about reads or writes within effect', () => {
331
+ it('should not warn about reads or writes within effect', async () => {
332
function Example() {
333
const ref = useRef(123);
334
useLayoutEffect(() => {
@@ -344,21 +344,21 @@ describe('useRef', () => {
344
return null;
345
}
346
347
- act(() => {
347
+ await act(async () => {
348
ReactNoop.render(<Example />);
349
});
350
351
ReactNoop.flushPassiveEffects();
352
});
353
354
- it('should not warn about reads or writes outside of render phase (e.g. event handler)', () => {
354
+ it('should not warn about reads or writes outside of render phase (e.g. event handler)', async () => {
355
let ref;
356
function Example() {
357
ref = useRef(123);
358
return null;
359
}
360
361
- act(() => {
361
+ await act(async () => {
362
ReactNoop.render(<Example />);
363
});
364
packages/react-reconciler/src/__tests__/useSyncExternalStore-test.js
+3
-3
@@ -195,19 +195,19 @@ describe('useSyncExternalStore', () => {
195
}
196
197
const root = ReactNoop.createRoot();
198
- act(() => {
198
+ await act(async () => {
199
// Start a render that reads from the store and yields value
200
root.render(<App />);
201
});
202
assertLog(['value:initial']);
203
204
- await act(() => {
204
+ await act(async () => {
205
store.set('value:changed');
206
});
207
assertLog(['value:changed']);
208
209
// If cached value was updated, we expect a re-render
210
- await act(() => {
210
+ await act(async () => {
211
store.set('value:initial');
212
});
213
assertLog(['value:initial']);
packages/react-refresh/src/__tests__/ReactFresh-test.js
+4
-2
@@ -17,6 +17,7 @@ let ReactDOMClient;
17
let ReactFreshRuntime;
18
let Scheduler;
19
let act;
20
+let internalAct;
21
let createReactClass;
22
let waitFor;
23
let assertLog;
@@ -33,7 +34,8 @@ describe('ReactFresh', () => {
34
ReactDOM = require('react-dom');
35
ReactDOMClient = require('react-dom/client');
36
Scheduler = require('scheduler');
36
- act = require('jest-react').act;
37
+ act = require('react-dom/test-utils').act;
38
+ internalAct = require('jest-react').act;
39
40
const InternalTestUtils = require('internal-test-utils');
41
waitFor = InternalTestUtils.waitFor;
@@ -2480,7 +2482,7 @@ describe('ReactFresh', () => {
2482
expect(el.firstChild.textContent).toBe('0');
2483
expect(el.firstChild.style.color).toBe('red');
2484
2483
- await act(async () => {
2485
+ await internalAct(async () => {
2486
el.firstChild.dispatchEvent(
2487
new MouseEvent('click', {
2488
bubbles: true,
packages/react-refresh/src/__tests__/ReactFreshIntegration-test.js
+1
-1
@@ -31,7 +31,7 @@ describe('ReactFreshIntegration', () => {
31
ReactFreshRuntime = require('react-refresh/runtime');
32
ReactFreshRuntime.injectIntoGlobalHook(global);
33
ReactDOM = require('react-dom');
34
- act = require('jest-react').act;
34
+ act = require('react-dom/test-utils').act;
35
container = document.createElement('div');
36
document.body.appendChild(container);
37
exportsObj = undefined;
packages/react-server-dom-relay/src/__tests__/ReactFlightDOMRelay-test.internal.js
+2
-2
@@ -85,7 +85,7 @@ describe('ReactFlightDOMRelay', () => {
85
});
86
});
87
88
- it('can render a Client Component using a module reference and render there', () => {
88
+ it('can render a Client Component using a module reference and render there', async () => {
89
function UserClient(props) {
90
return (
91
<span>
@@ -110,7 +110,7 @@ describe('ReactFlightDOMRelay', () => {
110
111
const container = document.createElement('div');
112
const root = ReactDOMClient.createRoot(container);
113
- act(() => {
113
+ await act(async () => {
114
root.render(modelClient.greeting);
115
});
116
packages/use-subscription/src/__tests__/useSubscription-test.js
+32
-24
@@ -81,7 +81,7 @@ describe('useSubscription', () => {
81
82
const observable = createBehaviorSubject();
83
let renderer;
84
- act(() => {
84
+ await act(async () => {
85
renderer = ReactTestRenderer.create(
86
<Subscription source={observable} />,
87
{unstable_isConcurrent: true},
@@ -90,14 +90,14 @@ describe('useSubscription', () => {
90
assertLog(['default']);
91
92
// Updates while subscribed should re-render the child component
93
- act(() => observable.next(123));
93
+ await act(async () => observable.next(123));
94
assertLog([123]);
95
- act(() => observable.next('abc'));
95
+ await act(async () => observable.next('abc'));
96
assertLog(['abc']);
97
98
// Unmounting the subscriber should remove listeners
99
- act(() => renderer.update(<div />));
100
- act(() => observable.next(456));
99
+ await act(async () => renderer.update(<div />));
100
+ await act(async () => observable.next(456));
101
await waitForAll([]);
102
});
103
@@ -133,21 +133,23 @@ describe('useSubscription', () => {
133
134
let observable = createReplaySubject('initial');
135
let renderer;
136
- act(() => {
136
+ await act(async () => {
137
renderer = ReactTestRenderer.create(
138
<Subscription source={observable} />,
139
{unstable_isConcurrent: true},
140
);
141
});
142
assertLog(['initial']);
143
- act(() => observable.next('updated'));
143
+ await act(async () => observable.next('updated'));
144
assertLog(['updated']);
145
146
await waitForAll([]);
147
148
// Unsetting the subscriber prop should reset subscribed values
149
observable = createReplaySubject(undefined);
150
- act(() => renderer.update(<Subscription source={observable} />));
150
+ await act(async () =>
151
+ renderer.update(<Subscription source={observable} />),
152
+ );
153
assertLog(['default']);
154
});
155
@@ -182,7 +184,7 @@ describe('useSubscription', () => {
184
expect(subscriptions).toHaveLength(0);
185
186
let renderer;
185
- act(() => {
187
+ await act(async () => {
188
renderer = ReactTestRenderer.create(
189
<Subscription source={observableA} />,
190
{unstable_isConcurrent: true},
@@ -195,18 +197,20 @@ describe('useSubscription', () => {
197
expect(subscriptions[0]).toBe(observableA);
198
199
// Unsetting the subscriber prop should reset subscribed values
198
- act(() => renderer.update(<Subscription source={observableB} />));
200
+ await act(async () =>
201
+ renderer.update(<Subscription source={observableB} />),
202
+ );
203
204
assertLog(['b-0']);
205
expect(subscriptions).toHaveLength(2);
206
expect(subscriptions[1]).toBe(observableB);
207
208
// Updates to the old subscribable should not re-render the child component
205
- act(() => observableA.next('a-1'));
209
+ await act(async () => observableA.next('a-1'));
210
await waitForAll([]);
211
212
// Updates to the bew subscribable should re-render the child component
209
- act(() => observableB.next('b-1'));
213
+ await act(async () => observableB.next('b-1'));
214
assertLog(['b-1']);
215
216
expect(subscriptions).toHaveLength(2);
@@ -241,7 +245,7 @@ describe('useSubscription', () => {
245
expect(subscriptions).toHaveLength(0);
246
247
let renderer;
244
- act(() => {
248
+ await act(async () => {
249
renderer = ReactTestRenderer.create(
250
<Subscription source={observableA} />,
251
{unstable_isConcurrent: true},
@@ -254,17 +258,19 @@ describe('useSubscription', () => {
258
expect(subscriptions[0]).toBe(observableA);
259
260
// Unsetting the subscriber prop should reset subscribed values
257
- act(() => renderer.update(<Subscription source={observableB} />));
261
+ await act(async () =>
262
+ renderer.update(<Subscription source={observableB} />),
263
+ );
264
assertLog(['b-0']);
265
expect(subscriptions).toHaveLength(2);
266
expect(subscriptions[1]).toBe(observableB);
267
268
// Updates to the old subscribable should not re-render the child component
263
- act(() => observableA.next('a-1'));
269
+ await act(async () => observableA.next('a-1'));
270
await waitForAll([]);
271
272
// Updates to the bew subscribable should re-render the child component
267
- act(() => observableB.next('b-1'));
273
+ await act(async () => observableB.next('b-1'));
274
assertLog(['b-1']);
275
276
expect(subscriptions).toHaveLength(2);
@@ -329,7 +335,7 @@ describe('useSubscription', () => {
335
const observableB = createBehaviorSubject('b-0');
336
337
let renderer;
332
- act(() => {
338
+ await act(async () => {
339
renderer = ReactTestRenderer.create(<Parent observed={observableA} />, {
340
unstable_isConcurrent: true,
341
});
@@ -353,7 +359,7 @@ describe('useSubscription', () => {
359
});
360
361
// Update again
356
- act(() => renderer.update(<Parent observed={observableA} />));
362
+ await act(async () => renderer.update(<Parent observed={observableA} />));
363
364
// Flush everything and ensure that the correct subscribable is used
365
// We expect the last emitted update to be rendered (because of the commit phase value check)
@@ -432,7 +438,7 @@ describe('useSubscription', () => {
438
const observableB = createBehaviorSubject('b-0');
439
440
let renderer;
435
- act(() => {
441
+ await act(async () => {
442
renderer = ReactTestRenderer.create(<Parent observed={observableA} />, {
443
unstable_isConcurrent: true,
444
});
@@ -474,12 +480,12 @@ describe('useSubscription', () => {
480
481
// Updates from the new subscribable should be ignored.
482
log.splice(0);
477
- act(() => observableB.next('b-1'));
483
+ await act(async () => observableB.next('b-1'));
484
await waitForAll([]);
485
expect(log).toEqual([]);
486
});
487
482
- it('should guard against updates that happen after unmounting', () => {
488
+ it('should guard against updates that happen after unmounting', async () => {
489
function Child({value = 'default'}) {
490
Scheduler.log(value);
491
return null;
@@ -529,7 +535,7 @@ describe('useSubscription', () => {
535
});
536
537
let renderer;
532
- act(() => {
538
+ await act(async () => {
539
renderer = ReactTestRenderer.create(
540
<Subscription source={eventHandler} />,
541
{unstable_isConcurrent: true},
@@ -563,7 +569,7 @@ describe('useSubscription', () => {
569
}
570
571
let renderer;
566
- act(() => {
572
+ await act(async () => {
573
renderer = ReactTestRenderer.create(
574
<Subscription subscription={subscription1} />,
575
{unstable_isConcurrent: true},
@@ -571,7 +577,9 @@ describe('useSubscription', () => {
577
});
578
await waitForAll([]);
579
574
- act(() => renderer.update(<Subscription subscription={subscription2} />));
580
+ await act(async () =>
581
+ renderer.update(<Subscription subscription={subscription2} />),
582
+ );
583
await waitForAll([]);
584
});
585