Skip to content

Commit

Permalink
test(eslint): create eslint test fixtures (#32396)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfaith authored Feb 16, 2025
1 parent 0d9834c commit 037b25c
Show file tree
Hide file tree
Showing 31 changed files with 3,629 additions and 944 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
{
"root": true,
"extends": ["plugin:react-hooks/recommended-legacy"],
"parserOptions": {
"ecmaVersion": 8,
"ecmaVersion": 2020,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": 2,
"react-hooks/exhaustive-deps": 2
"react-hooks/exhaustive-deps": "error"
}
}
12 changes: 12 additions & 0 deletions fixtures/eslint-v6/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# ESLint v6 Fixture

This fixture allows us to test e2e functionality for `eslint-plugin-react-hooks` with eslint version 6.

Run the following to test.

```sh
cd fixtures/eslint-v6
yarn
yarn build
yarn lint
```
5 changes: 5 additions & 0 deletions fixtures/eslint-v6/build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env node

import {exec} from 'node:child_process';

exec('cd ../.. && yarn build -r stable eslint-plugin-react-hooks');
143 changes: 143 additions & 0 deletions fixtures/eslint-v6/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/**
* Exhaustive Deps
*/
// Valid because dependencies are declared correctly
function Comment({comment, commentSource}) {
const currentUserID = comment.viewer.id;
const environment = RelayEnvironment.forUser(currentUserID);
const commentID = nullthrows(comment.id);
useEffect(() => {
const subscription = SubscriptionCounter.subscribeOnce(
`StoreSubscription_${commentID}`,
() =>
StoreSubscription.subscribe(
environment,
{
comment_id: commentID,
},
currentUserID,
commentSource
)
);
return () => subscription.dispose();
}, [commentID, commentSource, currentUserID, environment]);
}

// Valid because no dependencies
function UseEffectWithNoDependencies() {
const local = {};
useEffect(() => {
console.log(local);
});
}
function UseEffectWithEmptyDependencies() {
useEffect(() => {
const local = {};
console.log(local);
}, []);
}

// OK because `props` wasn't defined.
function ComponentWithNoPropsDefined() {
useEffect(() => {
console.log(props.foo);
}, []);
}

// Valid because props are declared as a dependency
function ComponentWithPropsDeclaredAsDep({foo}) {
useEffect(() => {
console.log(foo.length);
console.log(foo.slice(0));
}, [foo]);
}

// Valid because individual props are declared as dependencies
function ComponentWithIndividualPropsDeclaredAsDeps(props) {
useEffect(() => {
console.log(props.foo);
console.log(props.bar);
}, [props.bar, props.foo]);
}

// Invalid because neither props or props.foo are declared as dependencies
function ComponentWithoutDeclaringPropAsDep(props) {
useEffect(() => {
console.log(props.foo);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useCallback(() => {
console.log(props.foo);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useMemo(() => {
console.log(props.foo);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useEffect(() => {
console.log(props.foo);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useCallback(() => {
console.log(props.foo);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useMemo(() => {
console.log(props.foo);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.notReactiveHook(() => {
console.log(props.foo);
}, []); // This one isn't a violation
}

/**
* Rules of Hooks
*/
// Valid because functions can call functions.
function normalFunctionWithConditionalFunction() {
if (cond) {
doSomething();
}
}

// Valid because hooks can call hooks.
function useHook() {
useState();
}
const whatever = function useHook() {
useState();
};
const useHook1 = () => {
useState();
};
let useHook2 = () => useState();
useHook2 = () => {
useState();
};

// Invalid because hooks can't be called in conditionals.
function ComponentWithConditionalHook() {
if (cond) {
// eslint-disable-next-line react-hooks/rules-of-hooks
useConditionalHook();
}
}

// Invalid because hooks can't be called in loops.
function useHookInLoops() {
while (a) {
// eslint-disable-next-line react-hooks/rules-of-hooks
useHook1();
if (b) return;
// eslint-disable-next-line react-hooks/rules-of-hooks
useHook2();
}
while (c) {
// eslint-disable-next-line react-hooks/rules-of-hooks
useHook3();
if (d) return;
// eslint-disable-next-line react-hooks/rules-of-hooks
useHook4();
}
}
12 changes: 12 additions & 0 deletions fixtures/eslint-v6/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"private": true,
"name": "eslint-v6",
"dependencies": {
"eslint": "^6",
"eslint-plugin-react-hooks": "link:../../build/node_modules/eslint-plugin-react-hooks"
},
"scripts": {
"build": "node build.mjs && yarn",
"lint": "eslint index.js --report-unused-disable-directives"
}
}
Loading

0 comments on commit 037b25c

Please sign in to comment.