Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading