Skip to content

Commit 037b25c

Browse files
authored
test(eslint): create eslint test fixtures (#32396)
1 parent 0d9834c commit 037b25c

31 files changed

+3629
-944
lines changed
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
{
22
"root": true,
3+
"extends": ["plugin:react-hooks/recommended-legacy"],
34
"parserOptions": {
4-
"ecmaVersion": 8,
5+
"ecmaVersion": 2020,
56
"sourceType": "module",
67
"ecmaFeatures": {
78
"jsx": true
89
}
910
},
10-
"plugins": ["react-hooks"],
1111
"rules": {
12-
"react-hooks/rules-of-hooks": 2,
13-
"react-hooks/exhaustive-deps": 2
12+
"react-hooks/exhaustive-deps": "error"
1413
}
1514
}

fixtures/eslint-v6/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# ESLint v6 Fixture
2+
3+
This fixture allows us to test e2e functionality for `eslint-plugin-react-hooks` with eslint version 6.
4+
5+
Run the following to test.
6+
7+
```sh
8+
cd fixtures/eslint-v6
9+
yarn
10+
yarn build
11+
yarn lint
12+
```

fixtures/eslint-v6/build.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env node
2+
3+
import {exec} from 'node:child_process';
4+
5+
exec('cd ../.. && yarn build -r stable eslint-plugin-react-hooks');

fixtures/eslint-v6/index.js

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/**
2+
* Exhaustive Deps
3+
*/
4+
// Valid because dependencies are declared correctly
5+
function Comment({comment, commentSource}) {
6+
const currentUserID = comment.viewer.id;
7+
const environment = RelayEnvironment.forUser(currentUserID);
8+
const commentID = nullthrows(comment.id);
9+
useEffect(() => {
10+
const subscription = SubscriptionCounter.subscribeOnce(
11+
`StoreSubscription_${commentID}`,
12+
() =>
13+
StoreSubscription.subscribe(
14+
environment,
15+
{
16+
comment_id: commentID,
17+
},
18+
currentUserID,
19+
commentSource
20+
)
21+
);
22+
return () => subscription.dispose();
23+
}, [commentID, commentSource, currentUserID, environment]);
24+
}
25+
26+
// Valid because no dependencies
27+
function UseEffectWithNoDependencies() {
28+
const local = {};
29+
useEffect(() => {
30+
console.log(local);
31+
});
32+
}
33+
function UseEffectWithEmptyDependencies() {
34+
useEffect(() => {
35+
const local = {};
36+
console.log(local);
37+
}, []);
38+
}
39+
40+
// OK because `props` wasn't defined.
41+
function ComponentWithNoPropsDefined() {
42+
useEffect(() => {
43+
console.log(props.foo);
44+
}, []);
45+
}
46+
47+
// Valid because props are declared as a dependency
48+
function ComponentWithPropsDeclaredAsDep({foo}) {
49+
useEffect(() => {
50+
console.log(foo.length);
51+
console.log(foo.slice(0));
52+
}, [foo]);
53+
}
54+
55+
// Valid because individual props are declared as dependencies
56+
function ComponentWithIndividualPropsDeclaredAsDeps(props) {
57+
useEffect(() => {
58+
console.log(props.foo);
59+
console.log(props.bar);
60+
}, [props.bar, props.foo]);
61+
}
62+
63+
// Invalid because neither props or props.foo are declared as dependencies
64+
function ComponentWithoutDeclaringPropAsDep(props) {
65+
useEffect(() => {
66+
console.log(props.foo);
67+
// eslint-disable-next-line react-hooks/exhaustive-deps
68+
}, []);
69+
useCallback(() => {
70+
console.log(props.foo);
71+
// eslint-disable-next-line react-hooks/exhaustive-deps
72+
}, []);
73+
useMemo(() => {
74+
console.log(props.foo);
75+
// eslint-disable-next-line react-hooks/exhaustive-deps
76+
}, []);
77+
React.useEffect(() => {
78+
console.log(props.foo);
79+
// eslint-disable-next-line react-hooks/exhaustive-deps
80+
}, []);
81+
React.useCallback(() => {
82+
console.log(props.foo);
83+
// eslint-disable-next-line react-hooks/exhaustive-deps
84+
}, []);
85+
React.useMemo(() => {
86+
console.log(props.foo);
87+
// eslint-disable-next-line react-hooks/exhaustive-deps
88+
}, []);
89+
React.notReactiveHook(() => {
90+
console.log(props.foo);
91+
}, []); // This one isn't a violation
92+
}
93+
94+
/**
95+
* Rules of Hooks
96+
*/
97+
// Valid because functions can call functions.
98+
function normalFunctionWithConditionalFunction() {
99+
if (cond) {
100+
doSomething();
101+
}
102+
}
103+
104+
// Valid because hooks can call hooks.
105+
function useHook() {
106+
useState();
107+
}
108+
const whatever = function useHook() {
109+
useState();
110+
};
111+
const useHook1 = () => {
112+
useState();
113+
};
114+
let useHook2 = () => useState();
115+
useHook2 = () => {
116+
useState();
117+
};
118+
119+
// Invalid because hooks can't be called in conditionals.
120+
function ComponentWithConditionalHook() {
121+
if (cond) {
122+
// eslint-disable-next-line react-hooks/rules-of-hooks
123+
useConditionalHook();
124+
}
125+
}
126+
127+
// Invalid because hooks can't be called in loops.
128+
function useHookInLoops() {
129+
while (a) {
130+
// eslint-disable-next-line react-hooks/rules-of-hooks
131+
useHook1();
132+
if (b) return;
133+
// eslint-disable-next-line react-hooks/rules-of-hooks
134+
useHook2();
135+
}
136+
while (c) {
137+
// eslint-disable-next-line react-hooks/rules-of-hooks
138+
useHook3();
139+
if (d) return;
140+
// eslint-disable-next-line react-hooks/rules-of-hooks
141+
useHook4();
142+
}
143+
}

fixtures/eslint-v6/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"private": true,
3+
"name": "eslint-v6",
4+
"dependencies": {
5+
"eslint": "^6",
6+
"eslint-plugin-react-hooks": "link:../../build/node_modules/eslint-plugin-react-hooks"
7+
},
8+
"scripts": {
9+
"build": "node build.mjs && yarn",
10+
"lint": "eslint index.js --report-unused-disable-directives"
11+
}
12+
}

0 commit comments

Comments
 (0)