Skip to content

Commit 8979766

Browse files
authored
[ESLint] Allow partial matches for custom Effect Hooks (#17663)
1 parent 7259231 commit 8979766

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,6 +3154,37 @@ const tests = {
31543154
`and use that variable in the cleanup function.`,
31553155
],
31563156
},
3157+
{
3158+
code: `
3159+
function MyComponent() {
3160+
const myRef = useRef();
3161+
useLayoutEffect_SAFE_FOR_SSR(() => {
3162+
const handleMove = () => {};
3163+
myRef.current.addEventListener('mousemove', handleMove);
3164+
return () => myRef.current.removeEventListener('mousemove', handleMove);
3165+
});
3166+
return <div ref={myRef} />;
3167+
}
3168+
`,
3169+
output: `
3170+
function MyComponent() {
3171+
const myRef = useRef();
3172+
useLayoutEffect_SAFE_FOR_SSR(() => {
3173+
const handleMove = () => {};
3174+
myRef.current.addEventListener('mousemove', handleMove);
3175+
return () => myRef.current.removeEventListener('mousemove', handleMove);
3176+
});
3177+
return <div ref={myRef} />;
3178+
}
3179+
`,
3180+
errors: [
3181+
`The ref value 'myRef.current' will likely have changed by the time ` +
3182+
`this effect cleanup function runs. If this ref points to a node ` +
3183+
`rendered by React, copy 'myRef.current' to a variable inside the effect, ` +
3184+
`and use that variable in the cleanup function.`,
3185+
],
3186+
options: [{additionalHooks: 'useLayoutEffect_SAFE_FOR_SSR'}],
3187+
},
31573188
{
31583189
// Autofix ignores constant primitives (leaving the ones that are there).
31593190
code: `

packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export default {
8181
// Get the reactive hook node.
8282
const reactiveHook = node.parent.callee;
8383
const reactiveHookName = getNodeWithoutReactNamespace(reactiveHook).name;
84-
const isEffect = reactiveHookName.endsWith('Effect');
84+
const isEffect = /Effect($|[^a-z])/g.test(reactiveHookName);
8585

8686
// Get the declared dependencies for this reactive hook. If there is no
8787
// second argument then the reactive callback will re-run on every render.

0 commit comments

Comments
 (0)