Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] support new config system #3429

Merged
merged 1 commit into from Oct 10, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,10 +6,12 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
## Unreleased

### Added
* support new config system ([#3429][] @jjangga0214)
* [`hook-use-state`]: add `allowDestructuredState` option ([#3449][] @ljharb)
* add [`sort-default-props`] and deprecate [`jsx-sort-default-props`] ([#1861][] @alexzherdev)

[#3449]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3449
[#3424]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3429
[#1861]: https://github.com/jsx-eslint/eslint-plugin-react/pull/1861

## [7.31.9] - 2022.10.09
Expand Down
206 changes: 171 additions & 35 deletions README.md
Expand Up @@ -15,9 +15,9 @@ React specific linting rules for `eslint`
npm install eslint eslint-plugin-react --save-dev
```

It is also possible to install ESLint globally rather than locally (using npm install eslint --global). However, this is not recommended, and any plugins or shareable configs that you use must be installed locally in either case.
It is also possible to install ESLint globally rather than locally (using `npm install -g eslint`). However, this is not recommended, and any plugins or shareable configs that you use must be installed locally in either case.

## Configuration
## Configuration (legacy: `.eslintrc*`)

Use [our preset](#recommended) to get reasonable defaults:

Expand Down Expand Up @@ -109,6 +109,174 @@ Enable the rules that you would like to use.
}
```

### Shareable configs

#### Recommended

This plugin exports a `recommended` configuration that enforces React good practices.

To enable this configuration use the `extends` property in your `.eslintrc` config file:

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

See [`eslint` documentation](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending configuration files.

#### All

This plugin also exports an `all` configuration that includes every available rule.
This pairs well with the `eslint:all` rule.

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

**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [parser options](https://eslint.org/docs/user-guide/configuring/language-options#specifying-parser-options).

## Configuration (new: `eslint.config.js`)

From [`v8.21.0`](https://github.com/eslint/eslint/releases/tag/v8.21.0), eslint announced a new config system.
In the new system, `.eslintrc*` is no longer used. `eslint.config.js` would be the default config file name.
In eslint `v8`, the legacy system (`.eslintrc*`) would still be supported, while in eslint `v9`, only the new system would be supported.
ljharb marked this conversation as resolved.
Show resolved Hide resolved

And from [`v8.23.0`](https://github.com/eslint/eslint/releases/tag/v8.23.0), eslint CLI starts to look up `eslint.config.js`.
**So, if your eslint is `>=8.23.0`, you're 100% ready to use the new config system.**

You might want to check out the official blog posts,

- <https://eslint.org/blog/2022/08/new-config-system-part-1/>
- <https://eslint.org/blog/2022/08/new-config-system-part-2/>
- <https://eslint.org/blog/2022/08/new-config-system-part-3/>

and the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new).

### Plugin

The default export of `eslint-plugin-react` is a plugin object.

```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: {
// ... any rules you want
'react/jsx-uses-react': 'error',
'react/jsx-uses-vars': 'error',
},
// ... others are omitted for brevity
},
];
```

### Configuring shared settings

Refer to the [official docs](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuring-shared-settings).

The schema of the `settings.react` object would be identical to that of what's already described above in the legacy config section.

<!-- markdownlint-disable-next-line no-duplicate-heading -->
### Shareable configs

There're also 3 shareable configs.

- `eslint-plugin-react/configs/all`
- `eslint-plugin-react/configs/recommended`
- `eslint-plugin-react/configs/jsx-runtime`

If your eslint.config.js is ESM, include the `.js` extension (e.g. `eslint-plugin-react/recommended.js`). Note that the next semver-major will require omitting the extension for these imports.

**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [`languageOptions.parserOptions`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects).

In the new config system, `plugin:` protocol(e.g. `plugin:react/recommended`) is no longer valid.
As eslint does not automatically import the preset config (shareable config), you explicitly do it by yourself.

```js
const reactRecommended = require('eslint-plugin-react/configs/recommended');

module.exports = [
reactRecommended, // This is not a plugin object, but a shareable config object
];
```

You can of course add/override some properties.

**Note**: Our shareable configs does not preconfigure `files` or [`languageOptions.globals`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files-new#configuration-objects).
For most of the cases, you probably want to configure some properties by yourself.

```js
const reactRecommended = require('eslint-plugin-react/configs/recommended');
const globals = require('globals');

module.exports = [
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
...reactRecommended,
languageOptions: {
...reactRecommended.languageOptions,
globals: {
...globals.serviceworker,
...globals.browser;
},
},
},
];
```

The above example is same as the example below, as the new config system is based on chaining.

```js
const reactRecommended = require('eslint-plugin-react/configs/recommended');
const globals = require('globals');

module.exports = [
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
...reactRecommended,
},
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
languageOptions: {
globals: {
...globals.serviceworker,
...globals.browser,
},
},
},
];
```

## List of supported rules

✔: Enabled in the [`recommended`](#recommended) configuration.\
Expand Down Expand Up @@ -226,44 +394,12 @@ Enable the rules that you would like to use.
| | 🔧 | | [react/jsx-wrap-multilines](docs/rules/jsx-wrap-multilines.md) | Disallow missing parentheses around multiline JSX |
<!-- AUTO-GENERATED-CONTENT:END -->

### Other useful plugins
## Other useful plugins

- Rules of Hooks: [eslint-plugin-react-hooks](https://github.com/facebook/react/tree/master/packages/eslint-plugin-react-hooks)
- JSX accessibility: [eslint-plugin-jsx-a11y](https://github.com/evcohen/eslint-plugin-jsx-a11y)
- React Native: [eslint-plugin-react-native](https://github.com/Intellicode/eslint-plugin-react-native)

## Shareable configurations

### Recommended

This plugin exports a `recommended` configuration that enforces React good practices.

To enable this configuration use the `extends` property in your `.eslintrc` config file:

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

See [`eslint` documentation](https://eslint.org/docs/user-guide/configuring/configuration-files#extending-configuration-files) for more information about extending configuration files.

### All

This plugin also exports an `all` configuration that includes every available rule.
This pairs well with the `eslint:all` rule.

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

**Note**: These configurations will import `eslint-plugin-react` and enable JSX in [parser options](https://eslint.org/docs/user-guide/configuring/language-options#specifying-parser-options).

## License

`eslint-plugin-react` is licensed under the [MIT License](https://opensource.org/licenses/mit-license.php).
Expand Down
124 changes: 124 additions & 0 deletions configs/all.js
@@ -0,0 +1,124 @@
'use strict';

const react = require('../index');

const plugin = Object.assign({}, react);
delete plugin.configs;

/* eslint-disable global-require */
const allRules = {
'boolean-prop-naming': require('../lib/rules/boolean-prop-naming'),
'button-has-type': require('../lib/rules/button-has-type'),
'default-props-match-prop-types': require('../lib/rules/default-props-match-prop-types'),
'destructuring-assignment': require('../lib/rules/destructuring-assignment'),
'display-name': require('../lib/rules/display-name'),
'forbid-component-props': require('../lib/rules/forbid-component-props'),
'forbid-dom-props': require('../lib/rules/forbid-dom-props'),
'forbid-elements': require('../lib/rules/forbid-elements'),
'forbid-foreign-prop-types': require('../lib/rules/forbid-foreign-prop-types'),
'forbid-prop-types': require('../lib/rules/forbid-prop-types'),
'function-component-definition': require('../lib/rules/function-component-definition'),
'hook-use-state': require('../lib/rules/hook-use-state'),
'iframe-missing-sandbox': require('../lib/rules/iframe-missing-sandbox'),
'jsx-boolean-value': require('../lib/rules/jsx-boolean-value'),
'jsx-child-element-spacing': require('../lib/rules/jsx-child-element-spacing'),
'jsx-closing-bracket-location': require('../lib/rules/jsx-closing-bracket-location'),
'jsx-closing-tag-location': require('../lib/rules/jsx-closing-tag-location'),
'jsx-curly-spacing': require('../lib/rules/jsx-curly-spacing'),
'jsx-curly-newline': require('../lib/rules/jsx-curly-newline'),
'jsx-equals-spacing': require('../lib/rules/jsx-equals-spacing'),
'jsx-filename-extension': require('../lib/rules/jsx-filename-extension'),
'jsx-first-prop-new-line': require('../lib/rules/jsx-first-prop-new-line'),
'jsx-handler-names': require('../lib/rules/jsx-handler-names'),
'jsx-indent': require('../lib/rules/jsx-indent'),
'jsx-indent-props': require('../lib/rules/jsx-indent-props'),
'jsx-key': require('../lib/rules/jsx-key'),
'jsx-max-depth': require('../lib/rules/jsx-max-depth'),
'jsx-max-props-per-line': require('../lib/rules/jsx-max-props-per-line'),
'jsx-newline': require('../lib/rules/jsx-newline'),
'jsx-no-bind': require('../lib/rules/jsx-no-bind'),
'jsx-no-comment-textnodes': require('../lib/rules/jsx-no-comment-textnodes'),
'jsx-no-constructed-context-values': require('../lib/rules/jsx-no-constructed-context-values'),
'jsx-no-duplicate-props': require('../lib/rules/jsx-no-duplicate-props'),
'jsx-no-leaked-render': require('../lib/rules/jsx-no-leaked-render'),
'jsx-no-literals': require('../lib/rules/jsx-no-literals'),
'jsx-no-script-url': require('../lib/rules/jsx-no-script-url'),
'jsx-no-target-blank': require('../lib/rules/jsx-no-target-blank'),
'jsx-no-useless-fragment': require('../lib/rules/jsx-no-useless-fragment'),
'jsx-one-expression-per-line': require('../lib/rules/jsx-one-expression-per-line'),
'jsx-no-undef': require('../lib/rules/jsx-no-undef'),
'jsx-curly-brace-presence': require('../lib/rules/jsx-curly-brace-presence'),
'jsx-pascal-case': require('../lib/rules/jsx-pascal-case'),
'jsx-fragments': require('../lib/rules/jsx-fragments'),
'jsx-props-no-multi-spaces': require('../lib/rules/jsx-props-no-multi-spaces'),
'jsx-props-no-spreading': require('../lib/rules/jsx-props-no-spreading'),
'jsx-sort-default-props': require('../lib/rules/jsx-sort-default-props'),
'jsx-sort-props': require('../lib/rules/jsx-sort-props'),
'jsx-space-before-closing': require('../lib/rules/jsx-space-before-closing'),
'jsx-tag-spacing': require('../lib/rules/jsx-tag-spacing'),
'jsx-uses-react': require('../lib/rules/jsx-uses-react'),
'jsx-uses-vars': require('../lib/rules/jsx-uses-vars'),
'jsx-wrap-multilines': require('../lib/rules/jsx-wrap-multilines'),
'no-invalid-html-attribute': require('../lib/rules/no-invalid-html-attribute'),
'no-access-state-in-setstate': require('../lib/rules/no-access-state-in-setstate'),
'no-adjacent-inline-elements': require('../lib/rules/no-adjacent-inline-elements'),
'no-array-index-key': require('../lib/rules/no-array-index-key'),
'no-arrow-function-lifecycle': require('../lib/rules/no-arrow-function-lifecycle'),
'no-children-prop': require('../lib/rules/no-children-prop'),
'no-danger': require('../lib/rules/no-danger'),
'no-danger-with-children': require('../lib/rules/no-danger-with-children'),
'no-deprecated': require('../lib/rules/no-deprecated'),
'no-did-mount-set-state': require('../lib/rules/no-did-mount-set-state'),
'no-did-update-set-state': require('../lib/rules/no-did-update-set-state'),
'no-direct-mutation-state': require('../lib/rules/no-direct-mutation-state'),
'no-find-dom-node': require('../lib/rules/no-find-dom-node'),
'no-is-mounted': require('../lib/rules/no-is-mounted'),
'no-multi-comp': require('../lib/rules/no-multi-comp'),
'no-namespace': require('../lib/rules/no-namespace'),
'no-set-state': require('../lib/rules/no-set-state'),
'no-string-refs': require('../lib/rules/no-string-refs'),
'no-redundant-should-component-update': require('../lib/rules/no-redundant-should-component-update'),
'no-render-return-value': require('../lib/rules/no-render-return-value'),
'no-this-in-sfc': require('../lib/rules/no-this-in-sfc'),
'no-typos': require('../lib/rules/no-typos'),
'no-unescaped-entities': require('../lib/rules/no-unescaped-entities'),
'no-unknown-property': require('../lib/rules/no-unknown-property'),
'no-unsafe': require('../lib/rules/no-unsafe'),
'no-unstable-nested-components': require('../lib/rules/no-unstable-nested-components'),
'no-unused-class-component-methods': require('../lib/rules/no-unused-class-component-methods'),
'no-unused-prop-types': require('../lib/rules/no-unused-prop-types'),
'no-unused-state': require('../lib/rules/no-unused-state'),
'no-will-update-set-state': require('../lib/rules/no-will-update-set-state'),
'prefer-es6-class': require('../lib/rules/prefer-es6-class'),
'prefer-exact-props': require('../lib/rules/prefer-exact-props'),
'prefer-read-only-props': require('../lib/rules/prefer-read-only-props'),
'prefer-stateless-function': require('../lib/rules/prefer-stateless-function'),
'prop-types': require('../lib/rules/prop-types'),
'react-in-jsx-scope': require('../lib/rules/react-in-jsx-scope'),
'require-default-props': require('../lib/rules/require-default-props'),
'require-optimization': require('../lib/rules/require-optimization'),
'require-render-return': require('../lib/rules/require-render-return'),
'self-closing-comp': require('../lib/rules/self-closing-comp'),
'sort-comp': require('../lib/rules/sort-comp'),
'sort-default-props': require('../lib/rules/sort-default-props'),
'sort-prop-types': require('../lib/rules/sort-prop-types'),
'state-in-constructor': require('../lib/rules/state-in-constructor'),
'static-property-placement': require('../lib/rules/static-property-placement'),
'style-prop-object': require('../lib/rules/style-prop-object'),
'void-dom-elements-no-children': require('../lib/rules/void-dom-elements-no-children'),
};
/* eslint-enable global-require */

module.exports = {
plugins: {
react: plugin,
},
languageOptions: {
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
rules: allRules,
};
15 changes: 15 additions & 0 deletions configs/jsx-runtime.js
@@ -0,0 +1,15 @@
'use strict';

const all = require('./all');

module.exports = Object.assign({}, all, {
languageOptions: Object.assign({}, all.languageOptions, {
parserOptions: Object.assign({}, all.languageOptions.parserOptions, {
jsxPragma: null, // for @typescript/eslint-parser
}),
}),
rules: {
'react/react-in-jsx-scope': 0,
'react/jsx-uses-react': 0,
},
});