Skip to content

Commit 3927f36

Browse files
committed
[eslint] Consider useRef() as ... as constant
Sometimes you need to use casts, eg: DefinitelyTyped/DefinitelyTyped#28884 (comment). This change ignores them and allows you to still omit the ref object from the deps list. Test Plan: unit tests
1 parent 1fd4543 commit 3927f36

File tree

4 files changed

+136
-13
lines changed

4 files changed

+136
-13
lines changed

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

+71-11
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,6 @@ const ESLintTester = require('eslint').RuleTester;
1111
const ReactHooksESLintPlugin = require('eslint-plugin-react-hooks');
1212
const ReactHooksESLintRule = ReactHooksESLintPlugin.rules['exhaustive-deps'];
1313

14-
ESLintTester.setDefaultConfig({
15-
parser: require.resolve('babel-eslint'),
16-
parserOptions: {
17-
ecmaVersion: 6,
18-
sourceType: 'module',
19-
},
20-
});
21-
2214
/**
2315
* A string template tag that removes padding from the left side of multi-line strings
2416
* @param {Array} strings array of code strings (only one expected)
@@ -6441,11 +6433,65 @@ const tests = {
64416433
],
64426434
};
64436435

6436+
const testsTypescript = {
6437+
valid: [
6438+
{
6439+
// `ref` is still constant, despite the cast.
6440+
code: normalizeIndent`
6441+
function MyComponent() {
6442+
const ref = useRef() as React.MutableRefObject<HTMLDivElement>;
6443+
useEffect(() => {
6444+
console.log(ref.current);
6445+
}, []);
6446+
}
6447+
`,
6448+
},
6449+
],
6450+
invalid: [
6451+
{
6452+
// `local` is still non-constant, despite the cast.
6453+
code: normalizeIndent`
6454+
function MyComponent() {
6455+
const local = {} as string;
6456+
useEffect(() => {
6457+
console.log(local);
6458+
}, []);
6459+
}
6460+
`,
6461+
errors: [
6462+
{
6463+
message:
6464+
"React Hook useEffect has a missing dependency: 'local'. " +
6465+
'Either include it or remove the dependency array.',
6466+
suggestions: [
6467+
{
6468+
desc: 'Update the dependencies array to be: [local]',
6469+
output: normalizeIndent`
6470+
function MyComponent() {
6471+
const local = {} as string;
6472+
useEffect(() => {
6473+
console.log(local);
6474+
}, [local]);
6475+
}
6476+
`,
6477+
},
6478+
],
6479+
},
6480+
],
6481+
},
6482+
],
6483+
};
6484+
64446485
// For easier local testing
64456486
if (!process.env.CI) {
64466487
let only = [];
64476488
let skipped = [];
6448-
[...tests.valid, ...tests.invalid].forEach(t => {
6489+
[
6490+
...tests.valid,
6491+
...tests.invalid,
6492+
...testsTypescript.valid,
6493+
...testsTypescript.invalid,
6494+
].forEach(t => {
64496495
if (t.skip) {
64506496
delete t.skip;
64516497
skipped.push(t);
@@ -6466,7 +6512,21 @@ if (!process.env.CI) {
64666512
};
64676513
tests.valid = tests.valid.filter(predicate);
64686514
tests.invalid = tests.invalid.filter(predicate);
6515+
testsTypescript.valid = testsTypescript.valid.filter(predicate);
6516+
testsTypescript.invalid = testsTypescript.invalid.filter(predicate);
64696517
}
64706518

6471-
const eslintTester = new ESLintTester();
6472-
eslintTester.run('react-hooks', ReactHooksESLintRule, tests);
6519+
const parserOptions = {
6520+
ecmaVersion: 6,
6521+
sourceType: 'module',
6522+
};
6523+
6524+
new ESLintTester({
6525+
parser: require.resolve('babel-eslint'),
6526+
parserOptions,
6527+
}).run('react-hooks', ReactHooksESLintRule, tests);
6528+
6529+
new ESLintTester({
6530+
parser: require.resolve('@typescript-eslint/parser'),
6531+
parserOptions,
6532+
}).run('react-hooks', ReactHooksESLintRule, testsTypescript);

packages/eslint-plugin-react-hooks/package.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525
"url": "https://github.com/facebook/react/issues"
2626
},
2727
"engines": {
28-
"node": ">=7"
28+
"node": ">=10"
2929
},
3030
"homepage": "https://reactjs.org/",
3131
"peerDependencies": {
3232
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
33+
},
34+
"dependencies": {
35+
"@typescript-eslint/parser": "^2.26.0"
3336
}
3437
}

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,13 @@ export default {
316316
if (def.node.type !== 'VariableDeclarator') {
317317
return false;
318318
}
319-
const init = def.node.init;
319+
let init = def.node.init;
320320
if (init == null) {
321321
return false;
322322
}
323+
while (init.type === 'TSAsExpression') {
324+
init = init.expression;
325+
}
323326
// Detect primitive constants
324327
// const foo = 42
325328
let declaration = def.node.parent;

yarn.lock

+57
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,11 @@
13191319
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd"
13201320
integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==
13211321

1322+
"@types/eslint-visitor-keys@^1.0.0":
1323+
version "1.0.0"
1324+
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
1325+
integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==
1326+
13221327
"@types/estree@*":
13231328
version "0.0.42"
13241329
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.42.tgz#8d0c1f480339efedb3e46070e22dd63e0430dd11"
@@ -1430,6 +1435,16 @@
14301435
dependencies:
14311436
"@types/yargs-parser" "*"
14321437

1438+
"@typescript-eslint/experimental-utils@2.26.0":
1439+
version "2.26.0"
1440+
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.26.0.tgz#063390c404d9980767d76274df386c0aa675d91d"
1441+
integrity sha512-RELVoH5EYd+JlGprEyojUv9HeKcZqF7nZUGSblyAw1FwOGNnmQIU8kxJ69fttQvEwCsX5D6ECJT8GTozxrDKVQ==
1442+
dependencies:
1443+
"@types/json-schema" "^7.0.3"
1444+
"@typescript-eslint/typescript-estree" "2.26.0"
1445+
eslint-scope "^5.0.0"
1446+
eslint-utils "^2.0.0"
1447+
14331448
"@typescript-eslint/experimental-utils@^1.13.0":
14341449
version "1.13.0"
14351450
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz#b08c60d780c0067de2fb44b04b432f540138301e"
@@ -1439,6 +1454,16 @@
14391454
"@typescript-eslint/typescript-estree" "1.13.0"
14401455
eslint-scope "^4.0.0"
14411456

1457+
"@typescript-eslint/parser@^2.26.0":
1458+
version "2.26.0"
1459+
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.26.0.tgz#385463615818b33acb72a25b39c03579df93d76f"
1460+
integrity sha512-+Xj5fucDtdKEVGSh9353wcnseMRkPpEAOY96EEenN7kJVrLqy/EVwtIh3mxcUz8lsFXW1mT5nN5vvEam/a5HiQ==
1461+
dependencies:
1462+
"@types/eslint-visitor-keys" "^1.0.0"
1463+
"@typescript-eslint/experimental-utils" "2.26.0"
1464+
"@typescript-eslint/typescript-estree" "2.26.0"
1465+
eslint-visitor-keys "^1.1.0"
1466+
14421467
"@typescript-eslint/typescript-estree@1.13.0":
14431468
version "1.13.0"
14441469
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz#8140f17d0f60c03619798f1d628b8434913dc32e"
@@ -1447,6 +1472,19 @@
14471472
lodash.unescape "4.0.1"
14481473
semver "5.5.0"
14491474

1475+
"@typescript-eslint/typescript-estree@2.26.0":
1476+
version "2.26.0"
1477+
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.26.0.tgz#d8132cf1ee8a72234f996519a47d8a9118b57d56"
1478+
integrity sha512-3x4SyZCLB4zsKsjuhxDLeVJN6W29VwBnYpCsZ7vIdPel9ZqLfIZJgJXO47MNUkurGpQuIBALdPQKtsSnWpE1Yg==
1479+
dependencies:
1480+
debug "^4.1.1"
1481+
eslint-visitor-keys "^1.1.0"
1482+
glob "^7.1.6"
1483+
is-glob "^4.0.1"
1484+
lodash "^4.17.15"
1485+
semver "^6.3.0"
1486+
tsutils "^3.17.1"
1487+
14501488
"@webassemblyjs/ast@1.8.5":
14511489
version "1.8.5"
14521490
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
@@ -5169,6 +5207,13 @@ eslint-utils@^1.3.1, eslint-utils@^1.4.3:
51695207
dependencies:
51705208
eslint-visitor-keys "^1.1.0"
51715209

5210+
eslint-utils@^2.0.0:
5211+
version "2.0.0"
5212+
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd"
5213+
integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA==
5214+
dependencies:
5215+
eslint-visitor-keys "^1.1.0"
5216+
51725217
eslint-visitor-keys@1.0.0:
51735218
version "1.0.0"
51745219
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
@@ -13210,6 +13255,18 @@ tslib@^1, tslib@^1.10.0, tslib@^1.9.0, tslib@^1.9.3:
1321013255
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a"
1321113256
integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==
1321213257

13258+
tslib@^1.8.1:
13259+
version "1.11.1"
13260+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
13261+
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
13262+
13263+
tsutils@^3.17.1:
13264+
version "3.17.1"
13265+
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
13266+
integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==
13267+
dependencies:
13268+
tslib "^1.8.1"
13269+
1321313270
tty-browserify@0.0.0:
1321413271
version "0.0.0"
1321513272
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"

0 commit comments

Comments
 (0)