Skip to content

Commit 5c6c48b

Browse files
committed
Add special message for ref.current
1 parent e0203cb commit 5c6c48b

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

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

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,12 +1263,43 @@ const tests = {
12631263
}, [ref1, ref2, props.someOtherRefs, props.color]);
12641264
}
12651265
`,
1266-
// TODO: special message for the ref case.
12671266
errors: [
12681267
"React Hook useEffect has missing dependencies: 'props.someOtherRefs' and 'props.color'. " +
12691268
'Either include them or remove the dependency array.',
12701269
],
12711270
},
1271+
{
1272+
code: `
1273+
function MyComponent(props) {
1274+
const ref1 = useRef();
1275+
const ref2 = useRef();
1276+
useEffect(() => {
1277+
ref1.current.focus();
1278+
console.log(ref2.current.textContent);
1279+
alert(props.someOtherRefs.current.innerHTML);
1280+
fetch(props.color);
1281+
}, [ref1.current, ref2.current, props.someOtherRefs, props.color]);
1282+
}
1283+
`,
1284+
output: `
1285+
function MyComponent(props) {
1286+
const ref1 = useRef();
1287+
const ref2 = useRef();
1288+
useEffect(() => {
1289+
ref1.current.focus();
1290+
console.log(ref2.current.textContent);
1291+
alert(props.someOtherRefs.current.innerHTML);
1292+
fetch(props.color);
1293+
}, [props.someOtherRefs, props.color, ref1, ref2]);
1294+
}
1295+
`,
1296+
errors: [
1297+
"React Hook useEffect has unnecessary dependencies: 'ref1.current' and 'ref2.current'. " +
1298+
'Either exclude them or remove the dependency array. ' +
1299+
"Mutable values like 'ref1.current' aren't valid dependencies " +
1300+
"because their mutation doesn't re-render a component.",
1301+
],
1302+
},
12721303
{
12731304
code: `
12741305
function MyComponent() {
@@ -1286,10 +1317,11 @@ const tests = {
12861317
}, [ref]);
12871318
}
12881319
`,
1289-
// TODO: special message for the ref case.
12901320
errors: [
12911321
"React Hook useEffect has an unnecessary dependency: 'ref.current'. " +
1292-
'Either exclude it or remove the dependency array.',
1322+
'Either exclude it or remove the dependency array. ' +
1323+
"Mutable values like 'ref.current' aren't valid dependencies " +
1324+
"because their mutation doesn't re-render a component.",
12931325
],
12941326
},
12951327
{

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ export default {
302302
let duplicateDependencies = new Set();
303303
let unnecessaryDependencies = new Set();
304304
let missingDependencies = new Set();
305+
let showRefCurrentWarning = false;
305306

306307
let actualDependencies = Array.from(dependencies.keys());
307308

@@ -382,14 +383,33 @@ export default {
382383
} or remove the dependency array.`
383384
);
384385
};
386+
let extraWarning = '';
387+
if (unnecessaryDependencies.size > 0) {
388+
let badRef = null;
389+
Array.from(unnecessaryDependencies.keys()).forEach(key => {
390+
if (badRef !== null) {
391+
return;
392+
}
393+
if (key.endsWith('.current')) {
394+
badRef = key;
395+
}
396+
});
397+
if (badRef !== null) {
398+
extraWarning =
399+
` Mutable values like '${badRef}' aren't valid dependencies ` +
400+
"because their mutation doesn't re-render a component.";
401+
}
402+
}
403+
385404
context.report({
386405
node: declaredDependenciesNode,
387406
message:
388407
`React Hook ${context.getSource(reactiveHook)} has ` +
389408
// To avoid a long message, show the next actionable item.
390409
(list(missingDependencies, 'a', 'missing', 'include') ||
391410
list(unnecessaryDependencies, 'an', 'unnecessary', 'exclude') ||
392-
list(duplicateDependencies, 'a', 'duplicate', 'omit')),
411+
list(duplicateDependencies, 'a', 'duplicate', 'omit')) +
412+
extraWarning,
393413
fix(fixer) {
394414
// TODO: consider keeping the comments?
395415
return fixer.replaceText(

0 commit comments

Comments
 (0)