Skip to content

Commit 86a74c9

Browse files
authoredApr 17, 2024··
refactor!: migrate from eslint-plugin-react to eslint react (#453)
1 parent 2ffa95a commit 86a74c9

File tree

8 files changed

+341
-855
lines changed

8 files changed

+341
-855
lines changed
 

Diff for: ‎README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ export default antfu({
471471
Running `npx eslint` should prompt you to install the required dependencies, otherwise, you can install them manually:
472472

473473
```bash
474-
npm i -D eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-refresh
474+
npm i -D @eslint-react/eslint-plugin eslint-plugin-react-hooks eslint-plugin-react-refresh
475475
```
476476

477477
#### Svelte

Diff for: ‎package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@
3939
"prepare": "simple-git-hooks"
4040
},
4141
"peerDependencies": {
42+
"@eslint-react/eslint-plugin": "^1.5.8",
4243
"@unocss/eslint-plugin": ">=0.50.0",
4344
"astro-eslint-parser": "^0.16.3",
4445
"eslint": ">=8.40.0",
4546
"eslint-plugin-astro": "^0.31.4",
4647
"eslint-plugin-format": ">=0.1.0",
47-
"eslint-plugin-react": "^7.33.2",
4848
"eslint-plugin-react-hooks": "^4.6.0",
4949
"eslint-plugin-react-refresh": "^0.4.4",
5050
"eslint-plugin-solid": "^0.13.2",
@@ -54,6 +54,9 @@
5454
"svelte-eslint-parser": "^0.33.1"
5555
},
5656
"peerDependenciesMeta": {
57+
"@eslint-react/eslint-plugin": {
58+
"optional": true
59+
},
5760
"@unocss/eslint-plugin": {
5861
"optional": true
5962
},
@@ -66,9 +69,6 @@
6669
"eslint-plugin-format": {
6770
"optional": true
6871
},
69-
"eslint-plugin-react": {
70-
"optional": true
71-
},
7272
"eslint-plugin-react-hooks": {
7373
"optional": true
7474
},
@@ -130,6 +130,7 @@
130130
"@antfu/eslint-config": "workspace:*",
131131
"@antfu/eslint-plugin-prettier": "^5.0.1-1",
132132
"@antfu/ni": "^0.21.12",
133+
"@eslint-react/eslint-plugin": "^1.5.8",
133134
"@eslint/config-inspector": "^0.4.6",
134135
"@stylistic/eslint-plugin-migrate": "^1.7.0",
135136
"@types/eslint": "^8.56.9",
@@ -144,7 +145,6 @@
144145
"eslint": "^9.0.0",
145146
"eslint-plugin-astro": "^0.34.0",
146147
"eslint-plugin-format": "^0.1.0",
147-
"eslint-plugin-react": "^7.34.1",
148148
"eslint-plugin-react-hooks": "^4.6.0",
149149
"eslint-plugin-react-refresh": "^0.4.6",
150150
"eslint-plugin-solid": "^0.13.2",

Diff for: ‎pnpm-lock.yaml

+254-807
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: ‎src/cli/constants.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export const dependenciesMap = {
9898
'astro-eslint-parser',
9999
],
100100
react: [
101-
'eslint-plugin-react',
101+
'@eslint-react/eslint-plugin',
102102
'eslint-plugin-react-hooks',
103103
'eslint-plugin-react-refresh',
104104
],

Diff for: ‎src/configs/react.ts

+73-38
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,89 @@
11
import { isPackageExists } from 'local-pkg'
2-
import { ensurePackages, interopDefault } from '../utils'
3-
import type { OptionsFiles, OptionsHasTypeScript, OptionsOverrides, TypedFlatConfigItem } from '../types'
4-
import { GLOB_JSX, GLOB_TSX } from '../globs'
2+
import { ensurePackages, interopDefault, toArray } from '../utils'
3+
import type { OptionsFiles, OptionsOverrides, OptionsTypeScriptWithTypes, TypedFlatConfigItem } from '../types'
4+
import { GLOB_TS, GLOB_TSX } from '../globs'
55

66
// react refresh
77
const ReactRefreshAllowConstantExportPackages = [
88
'vite',
99
]
1010

1111
export async function react(
12-
options: OptionsHasTypeScript & OptionsOverrides & OptionsFiles = {},
12+
options: OptionsTypeScriptWithTypes & OptionsOverrides & OptionsFiles = {},
1313
): Promise<TypedFlatConfigItem[]> {
1414
const {
15-
files = [GLOB_JSX, GLOB_TSX],
15+
files = [GLOB_TS, GLOB_TSX],
1616
overrides = {},
17-
typescript = true,
1817
} = options
1918

2019
await ensurePackages([
21-
'eslint-plugin-react',
20+
'@eslint-react/eslint-plugin',
2221
'eslint-plugin-react-hooks',
2322
'eslint-plugin-react-refresh',
2423
])
2524

25+
const tsconfigPath = options?.tsconfigPath
26+
? toArray(options.tsconfigPath)
27+
: undefined
28+
const isTypeAware = !!tsconfigPath
29+
2630
const [
2731
pluginReact,
2832
pluginReactHooks,
2933
pluginReactRefresh,
34+
parserTs,
3035
] = await Promise.all([
31-
interopDefault(import('eslint-plugin-react')),
36+
interopDefault(import('@eslint-react/eslint-plugin')),
3237
interopDefault(import('eslint-plugin-react-hooks')),
3338
interopDefault(import('eslint-plugin-react-refresh')),
39+
interopDefault(import('@typescript-eslint/parser')),
3440
] as const)
3541

3642
const isAllowConstantExport = ReactRefreshAllowConstantExportPackages.some(
3743
i => isPackageExists(i),
3844
)
3945

46+
const plugins = pluginReact.configs.all.plugins
47+
4048
return [
4149
{
4250
name: 'antfu/react/setup',
4351
plugins: {
44-
'react': pluginReact,
52+
'react': plugins['@eslint-react'],
53+
'react-dom': plugins['@eslint-react/dom'],
4554
'react-hooks': pluginReactHooks,
55+
'react-hooks-extra': plugins['@eslint-react/hooks-extra'],
56+
'react-naming-convention': plugins['@eslint-react/naming-convention'],
4657
'react-refresh': pluginReactRefresh,
4758
},
48-
settings: {
49-
react: {
50-
version: 'detect',
51-
},
52-
},
5359
},
5460
{
5561
files,
5662
languageOptions: {
63+
parser: parserTs,
5764
parserOptions: {
5865
ecmaFeatures: {
5966
jsx: true,
6067
},
68+
...isTypeAware ? { project: tsconfigPath } : {},
6169
},
70+
sourceType: 'module',
6271
},
6372
name: 'antfu/react/rules',
6473
rules: {
74+
// recommended rules from @eslint-react/dom
75+
'react-dom/no-children-in-void-dom-elements': 'warn',
76+
'react-dom/no-dangerously-set-innerhtml': 'warn',
77+
'react-dom/no-dangerously-set-innerhtml-with-children': 'error',
78+
'react-dom/no-find-dom-node': 'error',
79+
'react-dom/no-missing-button-type': 'warn',
80+
'react-dom/no-missing-iframe-sandbox': 'warn',
81+
'react-dom/no-namespace': 'error',
82+
'react-dom/no-render-return-value': 'error',
83+
'react-dom/no-script-url': 'warn',
84+
'react-dom/no-unsafe-iframe-sandbox': 'warn',
85+
'react-dom/no-unsafe-target-blank': 'warn',
86+
6587
// recommended rules react-hooks
6688
'react-hooks/exhaustive-deps': 'warn',
6789
'react-hooks/rules-of-hooks': 'error',
@@ -72,34 +94,47 @@ export async function react(
7294
{ allowConstantExport: isAllowConstantExport },
7395
],
7496

75-
// recommended rules react
76-
'react/display-name': 'error',
77-
'react/jsx-key': 'error',
78-
'react/jsx-no-comment-textnodes': 'error',
79-
'react/jsx-no-duplicate-props': 'error',
80-
'react/jsx-no-target-blank': 'error',
81-
'react/jsx-no-undef': 'error',
82-
'react/jsx-uses-react': 'error',
83-
'react/jsx-uses-vars': 'error',
84-
'react/no-children-prop': 'error',
85-
'react/no-danger-with-children': 'error',
86-
'react/no-deprecated': 'error',
97+
// recommended rules from @eslint-react
98+
'react/ensure-forward-ref-using-ref': 'warn',
99+
'react/no-access-state-in-setstate': 'error',
100+
'react/no-array-index-key': 'warn',
101+
'react/no-children-count': 'warn',
102+
'react/no-children-for-each': 'warn',
103+
'react/no-children-map': 'warn',
104+
'react/no-children-only': 'warn',
105+
'react/no-children-prop': 'warn',
106+
'react/no-children-to-array': 'warn',
107+
'react/no-clone-element': 'warn',
108+
'react/no-comment-textnodes': 'warn',
109+
'react/no-component-will-mount': 'error',
110+
'react/no-component-will-receive-props': 'error',
111+
'react/no-component-will-update': 'error',
112+
'react/no-create-ref': 'error',
87113
'react/no-direct-mutation-state': 'error',
88-
'react/no-find-dom-node': 'error',
89-
'react/no-is-mounted': 'error',
90-
'react/no-render-return-value': 'error',
114+
'react/no-duplicate-key': 'error',
115+
'react/no-implicit-key': 'error',
116+
'react/no-missing-key': 'error',
117+
'react/no-nested-components': 'warn',
118+
'react/no-redundant-should-component-update': 'error',
119+
'react/no-set-state-in-component-did-mount': 'warn',
120+
'react/no-set-state-in-component-did-update': 'warn',
121+
'react/no-set-state-in-component-will-update': 'warn',
91122
'react/no-string-refs': 'error',
92-
'react/no-unescaped-entities': 'error',
93-
'react/no-unknown-property': 'error',
94-
'react/no-unsafe': 'off',
95-
'react/prop-types': 'error',
96-
'react/react-in-jsx-scope': 'off',
97-
'react/require-render-return': 'error',
123+
'react/no-unsafe-component-will-mount': 'warn',
124+
'react/no-unsafe-component-will-receive-props': 'warn',
125+
'react/no-unsafe-component-will-update': 'warn',
126+
'react/no-unstable-context-value': 'error',
127+
'react/no-unstable-default-props': 'error',
128+
'react/no-unused-class-component-members': 'warn',
129+
'react/no-unused-state': 'warn',
130+
'react/no-useless-fragment': 'warn',
131+
'react/prefer-destructuring-assignment': 'warn',
132+
'react/prefer-shorthand-boolean': 'warn',
133+
'react/prefer-shorthand-fragment': 'warn',
98134

99-
...typescript
135+
...isTypeAware
100136
? {
101-
'react/jsx-no-undef': 'off',
102-
'react/prop-type': 'off',
137+
'react/no-leaked-conditional-rendering': 'warn',
103138
}
104139
: {},
105140

Diff for: ‎src/factory.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ const VuePackages = [
5252
]
5353

5454
export const defaultPluginRenaming = {
55+
'@eslint-react': 'react',
56+
'@eslint-react/dom': 'react-dom',
57+
'@eslint-react/hooks-extra': 'react-hooks-extra',
58+
'@eslint-react/naming-convention': 'react-naming-convention',
59+
5560
'@stylistic': 'style',
5661
'@typescript-eslint': 'ts',
5762
'import-x': 'import',
@@ -168,7 +173,7 @@ export function antfu(
168173
if (enableReact) {
169174
configs.push(react({
170175
overrides: getOverrides(options, 'react'),
171-
typescript: !!enableTypeScript,
176+
tsconfigPath: getOverrides(options, 'typescript').tsconfigPath,
172177
}))
173178
}
174179

Diff for: ‎src/stub.d.ts

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
declare module 'eslint-plugin-react'
21
declare module 'eslint-plugin-react-hooks'
32
declare module 'eslint-plugin-react-refresh'

Diff for: ‎src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ export interface OptionsConfig extends OptionsComponentExts {
286286
* Enable react rules.
287287
*
288288
* Requires installing:
289-
* - `eslint-plugin-react`
289+
* - `@eslint-react/eslint-plugin`
290290
* - `eslint-plugin-react-hooks`
291291
* - `eslint-plugin-react-refresh`
292292
*

0 commit comments

Comments
 (0)
Please sign in to comment.