# eslint-plugin-react: The React Rules That Ship With Almost Every React Project

> eslint-plugin-react supplies React-specific lint rules for ESLint, from JSX usage to prop type checks. It installs from npm, ships presets for both config systems, and its accuracy depends on how much of the shared settings block you fill in.

**jsx-eslint/eslint-plugin-react** — React-specific linting rules for ESLint

- Repository: https://github.com/jsx-eslint/eslint-plugin-react
- Stars: 9,293 · Forks: 2,724
- Language: JavaScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/jsx-eslint-eslint-plugin-react

## What eslint-plugin-react actually adds to ESLint

ESLint on its own understands JavaScript syntax, not React semantics. It cannot tell that a variable is only used inside JSX, that a component declares a propType it never reads, or that a prop named class should be className. eslint-plugin-react is the rule package that teaches it those things. The package.json describes it plainly as React specific linting rules for ESLint, and the README opens the same way.

The audience is narrow and obvious: teams writing React with JSX who already run ESLint. If your project is React Native, the README does not address it; the related searches people run include a native variant, but that is a different plugin and the documentation says nothing about it. If you use TypeScript without JSX, most of the value disappears, because the rules are about JSX usage, prop types and component structure.

## How the rules decide what a component is

The mechanism is a settings block shared across every rule in the plugin. The README lists the keys: react.pragma (default React), react.fragment (default Fragment), react.createClass (default createReactClass), react.version (default detect, which reads the installed React version), react.defaultVersion and react.flowVersion. These are not cosmetic. A rule that looks for JSX must know which identifier opens it; a rule that checks fragments must know which name means fragment.

The second mechanism is wrapper lists. propWrapperFunctions names functions that wrap propTypes, for example forbidExtraProps, or an object form like {"property": "freeze", "object": "Object"}. componentWrapperFunctions names functions that wrap components, such as an observer from Mobx, with the option to set "object": "<pragma>" so it resolves to whatever react.pragma is. formComponents and linkComponents let you declare your own replacements for form and a. The README is explicit about the failure mode: if propTypes are wrapped in a function that is not listed, any propTypes wrapped in a function will be skipped. That is a silent skip, not a warning, and it is the single most common reason a team believes a rule is running when it is not.

Configuration arrives in two shapes. The legacy .eslintrc* system uses extends with plugin:react/recommended or plugin:react/all. The flat config system, default from ESLint v9, exports the plugin object as the default export, which you place under plugins. The README notes that from ESLint v8.21.0 the new system was announced and that v9 supports only the new system.

## Installing eslint-plugin-react and running it once

The README gives one install command, and it installs ESLint alongside the plugin. The note that follows is worth reading: installing ESLint globally is possible but not recommended, and plugins must be installed locally either way.

```bash
npm install eslint eslint-plugin-react --save-dev
```

For the legacy config format, the README shows extending the preset. The recommended preset pairs with eslint:recommended. If you use the React 17 JSX transform, the README says to also extend plugin:react/jsx-runtime to disable the rules that no longer apply.

```json
{
  "extends": [
    "eslint:recommended",
    "plugin:react/recommended"
  ]
}
```

For the flat config format, the plugin is the default export. The README's example registers it under plugins, enables JSX in parserOptions, and sets globals from the globals package. Note the file globs and the two rules it enables by hand.

```js
const react = require('eslint-plugin-react');
const globals = require('globals');

module.exports = [
  {
    files: ['**/*.{js,jsx,mjs,cjs,ts,tsx}'],
    plugins: { react },
    languageOptions: {
      parserOptions: { ecmaFeatures: { jsx: true } },
      globals: { ...globals.browser },
    },
    rules: {
      'react/jsx-uses-react': 'error',
      'react/jsx-uses-vars': 'error',
    },
  },
];
```

If you skip the presets, the README says you must add react to the plugins array, enable JSX in parserOptions.ecmaFeatures.jsx, and then turn rules on individually, with react/jsx-uses-react and react/jsx-uses-vars given as the two examples. After any of these setups, run your lint script and expect diagnostics to appear on JSX files; if nothing appears, the settings block is the first place to look.

## The settings block is where the plugin quietly fails

The README's settings example is long, and it is easy to paste only part of it. Two omissions cause the most damage. First, react.version. The README says detect picks the installed version automatically, that you can pin it to values like 16.0 or 16.3, and that it defaults to the defaultVersion setting, warns when missing, and will default to detect in the future. A project that never sets either value is relying on a behaviour the README itself describes as changing.

Second, the wrapper lists. Custom propTypes wrappers, Mobx observer components, and custom form or link components are all invisible to the rules until declared. The README's phrasing, that wrapped propTypes will be skipped, means you get a clean lint run and no coverage. That is the wrong failure direction for a linter.

There is also a scope limit worth stating plainly: this plugin checks React usage patterns. It does not check hook dependency arrays. The related searches for this project include hook questions, and the README does not document hooks rules; that responsibility sits with a separate plugin. Teams that install this one and assume hooks are covered are the clearest case of the wrong tool.

## eslint-plugin-react versus the newer React lint plugins

The related searches pair this plugin with @eslint-react/eslint-plugin, and the difference in approach is structural rather than a matter of rule counts. eslint-plugin-react is a plugin object consumed through the standard ESLint plugin interface: you register it, extend a preset or list rules, and configure behaviour through a shared settings.react block. That design is why it works with both .eslintrc* and eslint.config.js and why it has no opinions about your parser or your TypeScript setup.

The alternative family generally ships as a set of configs built for the flat config system, with rules organized around a newer rule set. Choosing between them is mostly a question of whether you want the broad, long-lived configuration surface this README documents, including the wrapper lists and pragma settings, or a smaller config-first package. If your project depends on custom propTypes wrappers or a non-default pragma, that configuration surface is the deciding factor, because the wrapper lists are what make the rules see your code at all.

A second comparison worth making is against ESLint itself. The recommended preset here is meant to be extended next to eslint:recommended, not instead of it. Dropping the core preset leaves you with React rules and no baseline JavaScript rules.

## Maintenance, versioning and the MIT licence

The repository is not archived. The last push was on 2026-07-30, which is recent enough that describing the project as maintained is fair on the evidence available. The release history is slower: v7.37.5 shipped on 2025-04-03, v7.37.4 on 2025-01-12, and v7.37.3 on 2024-12-23. Patch releases at that cadence suggest a stable rule set rather than rapid feature work, and the version line has stayed in 7.x across all three.

Upgrade cost is mostly configuration drift. Moving from .eslintrc* to eslint.config.js means rewriting how the plugin is registered, since the flat system uses the default export under plugins. The README points at the ESLint blog posts and docs for that migration rather than documenting it here. Preset changes between minor versions can surface new diagnostics in existing code, so a version bump is a lint run you should expect to triage.

The package is MIT licensed, which per the repository's LICENSE file permits commercial use and modification. That is a statement about the licence text, not legal advice; if your organization has a policy on dependency licences, route it through the people who own that policy.

## Conclusion

Adopt eslint-plugin-react if your codebase is plain React with JSX and you already run ESLint, since the plugin is the plugin object itself and the presets get you a sane rule set in two lines. Do not adopt it expecting hook correctness: that comes from eslint-plugin-react-hooks, and the README of this project does not cover it. Before rollout, verify your ESLint major against the flat config example in the README, confirm your React version resolves through settings.react.version, and check whether your propTypes are wrapped in a helper function, because unlisted wrappers are skipped by the propTypes rules.

## FAQ

### What does eslint-plugin-react do?

It is a package of React specific linting rules for ESLint. It teaches ESLint about JSX usage, prop types, fragments and component structure, and it exposes recommended and all presets plus a shared settings block under settings.react.

### How do I install eslint-plugin-react?

The README gives one command, npm install eslint eslint-plugin-react --save-dev, which installs ESLint and the plugin locally. It notes that installing ESLint globally is possible but not recommended, and that plugins must be installed locally either way.

### Is there an ESLint plugin for React that is compatible with ESLint 10?

The README does not state ESLint 10 support. It documents the flat config system, says the new config file is the default from ESLint v8.23.0 onward, and that ESLint v9 supports only the new system, so verify your ESLint major against the flat config example before upgrading.

### Is eslint-plugin-react deprecated?

The repository is not archived, and the last push was on 2026-07-30. The README documents current installation and configuration for both the legacy and flat config systems, so it is not presented as deprecated.

### How do I use the eslint plugin react hooks rules?

The README of this project does not document hooks rules. Its documented settings and presets cover JSX, prop types, form and link components, and wrapper functions, so hook dependency checking is not something this package provides according to its documentation.

## Sources

- [Issues](https://github.com/jsx-eslint/eslint-plugin-react/issues)
- [jsx-eslint/eslint-plugin-react on GitHub](https://github.com/jsx-eslint/eslint-plugin-react)
- [License: MIT](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/LICENSE)
- [README](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/README.md)
- [Releases](https://github.com/jsx-eslint/eslint-plugin-react/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jsx-eslint-eslint-plugin-react
