Skip to content

Commit f48f245

Browse files
committed
[eslint] Add an option to require dependencies on effect hooks
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 8ce15b0 commit f48f245

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)