» npm install eslint-plugin-react-dom
Videos
» npm install @eslint-react/eslint-plugin
» npm install eslint-plugin-react
» npm install eslint-plugin-react-hooks
Add this to your config in ESLint Config File, i.e. .eslintrc or eslint.config.js
{
"settings": {
"react": {
"version": "detect"
}
}
}
See the config here: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/README.md#configuration
Docs
https://eslint.org/docs/
https://eslint.org/docs/latest/use/configure/migration-guide
https://eslint.org/docs/latest/use/configure/configuration-files
If you're looking at the new eslint.config.js, I did the below (with typescript). I tried to follow the official README but it wasn't too helpful.
import react from "eslint-plugin-react";
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import typescriptParser from "@typescript-eslint/parser";
import globals from "globals";
import reactRecommended from "eslint-plugin-react/configs/recommended.js";
export default [
{
ignores: ["dist/**/*"],
},
{
files: ["**/*.{js,jsx,mjs,cjs,ts,tsx}"],
ignores: ["dist/**/*"],
...reactRecommended,
settings: {
version: "detect",
},
languageOptions: {
...reactRecommended.languageOptions,
ecmaVersion: "latest",
sourceType: "module",
parser: typescriptParser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
globals: {
...globals.serviceworker,
...globals.browser,
},
},
plugins: {
"@typescript-eslint": typescriptEslint,
react,
},
rules: {
//rules here
},
},
];
When I tried the config snippet in the question by @Jonathan Kasser, I got an error: TypeError: context.getSource is not a function.
The solution is to use fixupPluginRules from @eslint/compat (you need to install this), so my eslint.config.js has a separate object in the config array:
import { fixupPluginRules } from "@eslint/compat";
// Even though eslint-plugin-react-hooks exposes configs.recommended, it is not yet compatible with the flat file config,
// because it has plugins: [ 'react-hooks' ] property, but plugins should be an object
// Once it is supported, replace with: eslintPluginReactHooks.configs.recommended,
{
plugins: {
"react": reactPlugin, // remove this if you already have another config object that adds the react plugin
"react-hooks": fixupPluginRules(eslintPluginReactHooks),
},
rules: {
...eslintPluginReactHooks.configs.recommended.rules,
},
},
Resources
- https://github.com/t3-oss/create-t3-turbo/issues/984#issuecomment-2210934687
Proof it works
I've confirmed this by having a code that should error, and saw the error:
const [first, setfirst] = useState("");
useEffect(() => {
console.log(first);
}, []);
8:6 warning React Hook useEffect has a missing dependency: 'first'. Either include it or remove the dependency array react-hooks/exhaustive-deps
[email protected] was released a few weeks ago with "stable" eslint v9 support. If you can upgrade, then see https://github.com/facebook/react/issues/28313#issuecomment-2408157792 for a sample configuration for now.
Also, follow this thread if interested in documentation refresh
Hey y’all! I recently published an ESLint plugin inspired by the You Might Not Need an Effect section of the React docs.
useEffect is meant to sync your component with external systems. Things like the DOM, timers, or network requests. But you've probably seen (or written 😅) components with effects that operate entirely internally. This pattern shows up a lot, especially when folks are still getting used to React’s mental model.
The plugin catches these unnecessary effects and suggests the simpler, more idiomatic pattern to make your code easier to follow, faster to run, and less error-prone.
Here's a quick example:
// ❌ This triggers a warning:
// 1. "This effect operates entirely on internal React state, with no external dependencies. It is likely unnecessary."
// 2. "Avoid storing derived state. Compute "fullName" directly during render."
useEffect(() => {
setFullName(firstName + ' ' + lastName);
}, [firstName, lastName]);
// ✅ Better:
const fullName = firstName + ' ' + lastName;I was surprised there wasn’t already an official rule for this. Turns out it’s tricky to formalize something this abstract. But I’ve thrown a lot of tests at it and tried it on real-world codebases with success.
Would be super curious to hear if this is useful to you, or if you run into false positives or negatives, edge cases, or just have ideas for improvement.
Repo: https://github.com/NickvanDyke/eslint-plugin-react-you-might-not-need-an-effect
I hope it helps you write simpler, more performant and maintainable React! 🙂