Skip to content

Commit 1ea22f8

Browse files
committed
Add another test just to be safe
1 parent 25aa2e5 commit 1ea22f8

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,165 @@ describe('ReactSuspenseWithNoopRenderer', () => {
15121512
);
15131513
});
15141514

1515+
it('does not call lifecycles of a suspended component (hooks)', async () => {
1516+
function TextWithLifecycle(props) {
1517+
React.useLayoutEffect(
1518+
() => {
1519+
Scheduler.unstable_yieldValue(`Layout Effect [${props.text}]`);
1520+
return () => {
1521+
Scheduler.unstable_yieldValue(
1522+
`Destroy Layout Effect [${props.text}]`,
1523+
);
1524+
};
1525+
},
1526+
[props.text],
1527+
);
1528+
React.useEffect(
1529+
() => {
1530+
Scheduler.unstable_yieldValue(`Effect [${props.text}]`);
1531+
return () => {
1532+
Scheduler.unstable_yieldValue(`Destroy Effect [${props.text}]`);
1533+
};
1534+
},
1535+
[props.text],
1536+
);
1537+
return <Text {...props} />;
1538+
}
1539+
1540+
function AsyncTextWithLifecycle(props) {
1541+
React.useLayoutEffect(
1542+
() => {
1543+
Scheduler.unstable_yieldValue(`Layout Effect [${props.text}]`);
1544+
return () => {
1545+
Scheduler.unstable_yieldValue(
1546+
`Destroy Layout Effect [${props.text}]`,
1547+
);
1548+
};
1549+
},
1550+
[props.text],
1551+
);
1552+
React.useEffect(
1553+
() => {
1554+
Scheduler.unstable_yieldValue(`Effect [${props.text}]`);
1555+
return () => {
1556+
Scheduler.unstable_yieldValue(`Destroy Effect [${props.text}]`);
1557+
};
1558+
},
1559+
[props.text],
1560+
);
1561+
const text = props.text;
1562+
const ms = props.ms;
1563+
try {
1564+
TextResource.read([text, ms]);
1565+
Scheduler.unstable_yieldValue(text);
1566+
return <span prop={text} />;
1567+
} catch (promise) {
1568+
if (typeof promise.then === 'function') {
1569+
Scheduler.unstable_yieldValue(`Suspend! [${text}]`);
1570+
} else {
1571+
Scheduler.unstable_yieldValue(`Error! [${text}]`);
1572+
}
1573+
throw promise;
1574+
}
1575+
}
1576+
1577+
function App({text}) {
1578+
return (
1579+
<Suspense fallback={<TextWithLifecycle text="Loading..." />}>
1580+
<TextWithLifecycle text="A" />
1581+
<AsyncTextWithLifecycle ms={100} text={text} />
1582+
<TextWithLifecycle text="C" />
1583+
</Suspense>
1584+
);
1585+
}
1586+
1587+
ReactNoop.renderLegacySyncRoot(<App text="B" />, () =>
1588+
Scheduler.unstable_yieldValue('Commit root'),
1589+
);
1590+
expect(Scheduler).toHaveYielded([
1591+
'A',
1592+
'Suspend! [B]',
1593+
'C',
1594+
'Loading...',
1595+
1596+
'Layout Effect [A]',
1597+
// B's effect should not fire because it suspended
1598+
// 'Layout Effect [B]',
1599+
'Layout Effect [C]',
1600+
'Layout Effect [Loading...]',
1601+
'Commit root',
1602+
]);
1603+
1604+
// Flush passive effects.
1605+
expect(Scheduler).toFlushAndYield([
1606+
'Effect [A]',
1607+
// B's effect should not fire because it suspended
1608+
// 'Effect [B]',
1609+
'Effect [C]',
1610+
'Effect [Loading...]',
1611+
]);
1612+
1613+
expect(ReactNoop).toMatchRenderedOutput(
1614+
<>
1615+
<span hidden={true} prop="A" />
1616+
<span hidden={true} prop="C" />
1617+
<span prop="Loading..." />
1618+
</>,
1619+
);
1620+
1621+
Scheduler.unstable_advanceTime(500);
1622+
await advanceTimers(500);
1623+
1624+
expect(Scheduler).toHaveYielded(['Promise resolved [B]']);
1625+
1626+
expect(Scheduler).toFlushAndYield([
1627+
'B',
1628+
'Destroy Layout Effect [Loading...]',
1629+
'Destroy Effect [Loading...]',
1630+
'Layout Effect [B]',
1631+
'Effect [B]',
1632+
]);
1633+
1634+
// Update
1635+
ReactNoop.renderLegacySyncRoot(<App text="B2" />, () =>
1636+
Scheduler.unstable_yieldValue('Commit root'),
1637+
);
1638+
1639+
expect(Scheduler).toHaveYielded([
1640+
'A',
1641+
'Suspend! [B2]',
1642+
'C',
1643+
'Loading...',
1644+
1645+
// B2's effect should not fire because it suspended
1646+
// 'Layout Effect [B2]',
1647+
'Layout Effect [Loading...]',
1648+
'Commit root',
1649+
]);
1650+
1651+
// Flush passive effects.
1652+
expect(Scheduler).toFlushAndYield([
1653+
// B2's effect should not fire because it suspended
1654+
// 'Effect [B2]',
1655+
'Effect [Loading...]',
1656+
]);
1657+
1658+
Scheduler.unstable_advanceTime(500);
1659+
await advanceTimers(500);
1660+
1661+
expect(Scheduler).toHaveYielded(['Promise resolved [B2]']);
1662+
1663+
expect(Scheduler).toFlushAndYield([
1664+
'B2',
1665+
'Destroy Layout Effect [Loading...]',
1666+
'Destroy Effect [Loading...]',
1667+
'Destroy Layout Effect [B]',
1668+
'Layout Effect [B2]',
1669+
'Destroy Effect [B]',
1670+
'Effect [B2]',
1671+
]);
1672+
});
1673+
15151674
it('suspends for longer if something took a long (CPU bound) time to render', async () => {
15161675
function Foo({renderContent}) {
15171676
Scheduler.unstable_yieldValue('Foo');

0 commit comments

Comments
 (0)