Skip to content

Commit 28a86ff

Browse files
committed
[lint] Allow useEffectEvent in useLayoutEffect and useInsertionEffect
1 parent 8e60cb7 commit 28a86ff

File tree

2 files changed

+69
-3
lines changed

2 files changed

+69
-3
lines changed

packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,72 @@ if (__EXPERIMENTAL__) {
14301430
}
14311431
`,
14321432
},
1433+
{
1434+
code: normalizeIndent`
1435+
// Valid because functions created with useEffectEvent can be called in useLayoutEffect.
1436+
function MyComponent({ theme }) {
1437+
const onClick = useEffectEvent(() => {
1438+
showNotification(theme);
1439+
});
1440+
useLayoutEffect(() => {
1441+
onClick();
1442+
});
1443+
React.useLayoutEffect(() => {
1444+
onClick();
1445+
});
1446+
}
1447+
`,
1448+
},
1449+
{
1450+
code: normalizeIndent`
1451+
// Valid because functions created with useEffectEvent can be called in useInsertionEffect.
1452+
function MyComponent({ theme }) {
1453+
const onClick = useEffectEvent(() => {
1454+
showNotification(theme);
1455+
});
1456+
useInsertionEffect(() => {
1457+
onClick();
1458+
});
1459+
React.useInsertionEffect(() => {
1460+
onClick();
1461+
});
1462+
}
1463+
`,
1464+
},
1465+
{
1466+
code: normalizeIndent`
1467+
// Valid because functions created with useEffectEvent can be passed by reference in useLayoutEffect
1468+
// and useInsertionEffect.
1469+
function MyComponent({ theme }) {
1470+
const onClick = useEffectEvent(() => {
1471+
showNotification(theme);
1472+
});
1473+
const onClick2 = useEffectEvent(() => {
1474+
debounce(onClick);
1475+
debounce(() => onClick());
1476+
debounce(() => { onClick() });
1477+
deboucne(() => debounce(onClick));
1478+
});
1479+
useLayoutEffect(() => {
1480+
let id = setInterval(() => onClick(), 100);
1481+
return () => clearInterval(onClick);
1482+
}, []);
1483+
React.useLayoutEffect(() => {
1484+
let id = setInterval(() => onClick(), 100);
1485+
return () => clearInterval(onClick);
1486+
}, []);
1487+
useInsertionEffect(() => {
1488+
let id = setInterval(() => onClick(), 100);
1489+
return () => clearInterval(onClick);
1490+
}, []);
1491+
React.useInsertionEffect(() => {
1492+
let id = setInterval(() => onClick(), 100);
1493+
return () => clearInterval(onClick);
1494+
}, []);
1495+
return null;
1496+
}
1497+
`,
1498+
},
14331499
];
14341500
allTests.invalid = [
14351501
...allTests.invalid,

packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ function getNodeWithoutReactNamespace(
147147
return node;
148148
}
149149

150-
function isUseEffectIdentifier(node: Node): boolean {
151-
return node.type === 'Identifier' && node.name === 'useEffect';
150+
function isEffectIdentifier(node: Node): boolean {
151+
return node.type === 'Identifier' && (node.name === 'useEffect' || node.name === 'useLayoutEffect' || node.name === 'useInsertionEffect');
152152
}
153153
function isUseEffectEventIdentifier(node: Node): boolean {
154154
if (__EXPERIMENTAL__) {
@@ -726,7 +726,7 @@ const rule = {
726726
// Check all `useEffect` and `React.useEffect`, `useEffectEvent`, and `React.useEffectEvent`
727727
const nodeWithoutNamespace = getNodeWithoutReactNamespace(node.callee);
728728
if (
729-
(isUseEffectIdentifier(nodeWithoutNamespace) ||
729+
(isEffectIdentifier(nodeWithoutNamespace) ||
730730
isUseEffectEventIdentifier(nodeWithoutNamespace)) &&
731731
node.arguments.length > 0
732732
) {

0 commit comments

Comments
 (0)