Skip to content

Commit 99efc62

Browse files
authored
[eslint] Add an option to require dependencies on effect hooks (facebook#33344)
Summary: To prepare for automatic effect dependencies, some codebases may want to codemod existing useEffect calls with no deps to include an explicit undefined second argument in order to preserve the "run on every render" behavior. In sufficiently large codebases, this may require a temporary enforcement period where all effects provide an explicit dependencies argument. Outside of migration, relying on a component to render can lead to real bugs, especially when working with memoization.
1 parent bfaeb4a commit 99efc62

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8344,6 +8344,23 @@ const testsTypescript = {
83448344
},
83458345
],
83468346
},
8347+
{
8348+
code: normalizeIndent`
8349+
function MyComponent(props) {
8350+
useEffect(() => {
8351+
console.log(props.foo);
8352+
});
8353+
}
8354+
`,
8355+
options: [{requireExplicitEffectDeps: true}],
8356+
errors: [
8357+
{
8358+
message:
8359+
'React Hook useEffect always requires dependencies. Please add a dependency array or an explicit `undefined`',
8360+
suggestions: undefined,
8361+
},
8362+
],
8363+
},
83478364
],
83488365
};
83498366

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ const rule = {
6767
type: 'string',
6868
},
6969
},
70+
requireExplicitEffectDeps: {
71+
type: 'boolean',
72+
}
7073
},
7174
},
7275
],
@@ -90,10 +93,13 @@ const rule = {
9093
? rawOptions.experimental_autoDependenciesHooks
9194
: [];
9295

96+
const requireExplicitEffectDeps: boolean = rawOptions && rawOptions.requireExplicitEffectDeps || false;
97+
9398
const options = {
9499
additionalHooks,
95100
experimental_autoDependenciesHooks,
96101
enableDangerousAutofixThisMayCauseInfiniteLoops,
102+
requireExplicitEffectDeps,
97103
};
98104

99105
function reportProblem(problem: Rule.ReportDescriptor) {
@@ -1340,6 +1346,15 @@ const rule = {
13401346
return;
13411347
}
13421348

1349+
if (!maybeNode && isEffect && options.requireExplicitEffectDeps) {
1350+
reportProblem({
1351+
node: reactiveHook,
1352+
message:
1353+
`React Hook ${reactiveHookName} always requires dependencies. ` +
1354+
`Please add a dependency array or an explicit \`undefined\``
1355+
});
1356+
}
1357+
13431358
const isAutoDepsHook =
13441359
options.experimental_autoDependenciesHooks.includes(reactiveHookName);
13451360

0 commit comments

Comments
 (0)