1305
});
1306
});
1307
1308
- it('shows a unique warning for state updates from within passive unmount function', () => {
1308
+ it('shows a warning when a component updates its own state from within passive unmount function', () => {
1309
function Component() {
1310
Scheduler.unstable_yieldValue('Component');
1311
const [didLoad, setDidLoad] = React.useState(false);
1334
expect(() => {
1335
expect(Scheduler).toFlushAndYield(['passive destroy']);
1336
}).toErrorDev(
1337
- "Warning: Can't perform a React state update from within a useEffect cleanup function.",
1337
+ "Warning: Can't perform a React state update from within a useEffect cleanup function. " +
1338
+ 'To fix, move state updates to the useEffect() body.\n' +
1339
+ ' in Component (at **)',
1340
);
1341
});
1342
});
1343
+
1344
+ it('shows a warning when a component updates a childs state from within passive unmount function', () => {
1345
+ function Parent() {
1346
+ Scheduler.unstable_yieldValue('Parent');
1347
+ const updaterRef = React.useRef(null);
1348
+ React.useEffect(() => {
1349
+ Scheduler.unstable_yieldValue('Parent passive create');
1350
+ return () => {
1351
+ updaterRef.current(true);
1352
+ Scheduler.unstable_yieldValue('Parent passive destroy');
1353
+ };
1354
+ }, []);
1355
+ return <Child updaterRef={updaterRef} />;
1356
+ }
1357
+
1358
+ function Child({updaterRef}) {
1359
+ Scheduler.unstable_yieldValue('Child');
1360
+ const [state, setState] = React.useState(false);
1361
+ React.useEffect(() => {
1362
+ Scheduler.unstable_yieldValue('Child passive create');
1363
+ updaterRef.current = setState;
1364
+ }, []);
1365
+ return state;
1366
+ }
1367
+
1368
+ act(() => {
1369
+ ReactNoop.renderToRootWithID(<Parent />, 'root');
1370
+ expect(Scheduler).toFlushAndYieldThrough([
1371
+ 'Parent',
1372
+ 'Child',
1373
+ 'Child passive create',
1374
+ 'Parent passive create',
1375
+ ]);
1376
+
1377
+ // Unmount but don't process pending passive destroy function
1378
+ ReactNoop.unmountRootWithID('root');
1379
+ expect(() => {
1380
+ expect(Scheduler).toFlushAndYield(['Parent passive destroy']);
1381
+ }).toErrorDev(
1382
+ "Warning: Can't perform a React state update from within a useEffect cleanup function. " +
1383
+ 'To fix, move state updates to the useEffect() body.\n' +
1384
+ ' in Parent (at **)',
1385
+ );
1386
+ });
1387
+ });
1388
+
1389
+ it('does not show a warning when a component updates a parents state from within passive unmount function', () => {
1390
+ function Parent() {
1391
+ const [state, setState] = React.useState(false);
1392
+ Scheduler.unstable_yieldValue('Parent');
1393
+ return <Child setState={setState} state={state} />;
1394
+ }
1395
+
1396
+ function Child({setState, state}) {
1397
+ Scheduler.unstable_yieldValue('Child');
1398
+ React.useEffect(() => {
1399
+ Scheduler.unstable_yieldValue('Child passive create');
1400
+ return () => {
1401
+ Scheduler.unstable_yieldValue('Child passive destroy');
1402
+ setState(true);
1403
+ };
1404
+ }, []);
1405
+ return state;
1406
+ }
1407
+
1408
+ act(() => {
1409
+ ReactNoop.renderToRootWithID(<Parent />, 'root');
1410
+ expect(Scheduler).toFlushAndYieldThrough([
1411
+ 'Parent',
1412
+ 'Child',
1413
+ 'Child passive create',
1414
+ ]);
1415
+
1416
+ // Unmount but don't process pending passive destroy function
1417
+ ReactNoop.unmountRootWithID('root');
1418
+ expect(Scheduler).toFlushAndYield(['Child passive destroy']);
1419
+ });
1420
+ });
1421
}
1422
1423
it('updates have async priority', () => {