Skip to content

Commit 768d34b

Browse files
committed
feat(plugins/x): add destructuring props support to 'no-forward-ref'
1 parent 34096b2 commit 768d34b

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

packages/plugins/eslint-plugin-react-x/src/rules/no-forward-ref.spec.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,14 +205,34 @@ ruleTester.run(RULE_NAME, rule, {
205205
code: /* tsx */ `
206206
import * as React from 'react'
207207
const Component = React.forwardRef<HTMLElement, { foo: string }>(function Component(props, ref) {
208-
return <div ref={ref} />;
208+
return <div ref={ref}>{props.foo}</div>;
209209
});
210210
`,
211211
errors: [{ messageId: "noForwardRef" }],
212212
output: /* tsx */ `
213213
import * as React from 'react'
214214
const Component = function Component({ ref, ...props }: { foo: string } & { ref: React.RefObject<HTMLElement> }) {
215-
return <div ref={ref} />;
215+
return <div ref={ref}>{props.foo}</div>;
216+
};
217+
`,
218+
settings: {
219+
"react-x": {
220+
version: "19.0.0",
221+
},
222+
},
223+
},
224+
{
225+
code: /* tsx */ `
226+
import * as React from 'react'
227+
const Component = React.forwardRef<HTMLElement, { foo: string }>(function Component({ foo }, ref) {
228+
return <div ref={ref}>{foo}</div>;
229+
});
230+
`,
231+
errors: [{ messageId: "noForwardRef" }],
232+
output: /* tsx */ `
233+
import * as React from 'react'
234+
const Component = function Component({ ref, foo }: { foo: string } & { ref: React.RefObject<HTMLElement> }) {
235+
return <div ref={ref}>{foo}</div>;
216236
};
217237
`,
218238
settings: {

packages/plugins/eslint-plugin-react-x/src/rules/no-forward-ref.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import * as AST from "@eslint-react/ast";
22
import { isForwardRefCall } from "@eslint-react/core";
33
import { decodeSettings, normalizeSettings } from "@eslint-react/shared";
4+
import { O } from "@eslint-react/tools";
45
import type { RuleContext } from "@eslint-react/types";
56
import type { TSESTree } from "@typescript-eslint/types";
67
import { AST_NODE_TYPES } from "@typescript-eslint/types";
78
import type { RuleFix, RuleFixer } from "@typescript-eslint/utils/ts-eslint";
89
import { compare } from "compare-versions";
910
import type { CamelCase } from "string-ts";
11+
import { match } from "ts-pattern";
1012

1113
import { createRule } from "../utils";
1214

@@ -68,16 +70,23 @@ function getComponentPropsFixes(
6870
fixer: RuleFixer,
6971
context: RuleContext,
7072
): RuleFix[] {
73+
const getText = (node: TSESTree.Node) => context.sourceCode.getText(node);
7174
const [arg0, arg1] = node.params;
7275
const [typeArg0, typeArg1] = typeArguments;
73-
if (arg0?.type !== AST_NODE_TYPES.Identifier) return [];
76+
if (!arg0) return [];
77+
const fixedArg0Text = match(arg0)
78+
.with({ type: AST_NODE_TYPES.Identifier }, (n) => O.some(`...${n.name}`))
79+
.with({ type: AST_NODE_TYPES.ObjectPattern }, (n) => O.some(n.properties.map(getText).join(", ")))
80+
.otherwise(O.none);
81+
if (O.isNone(fixedArg0Text)) return [];
82+
const fixedPropsText = fixedArg0Text.value;
7483
if (!arg1) {
7584
return [fixer.replaceText(
7685
arg0,
7786
[
7887
"{",
7988
"ref,",
80-
`...${arg0.name}`,
89+
fixedPropsText,
8190
"}",
8291
].join(" "),
8392
)] as const;
@@ -92,15 +101,14 @@ function getComponentPropsFixes(
92101
arg1.name === "ref"
93102
? `ref,`
94103
: `ref: ${arg1.name},`,
95-
`...${arg0.name}`,
104+
fixedPropsText,
96105
"}",
97106
].join(" "),
98107
),
99108
fixer.remove(arg1),
100109
fixer.removeRange([arg0.range[1], arg1.range[0]]),
101110
] as const;
102111
}
103-
const getText = (node: TSESTree.Node) => context.sourceCode.getText(node);
104112
return [
105113
fixer.replaceText(
106114
arg0,
@@ -109,7 +117,7 @@ function getComponentPropsFixes(
109117
arg1.name === "ref"
110118
? `ref,`
111119
: `ref: ${arg1.name},`,
112-
`...${arg0.name}`,
120+
fixedPropsText,
113121
"}:",
114122
getText(typeArg1),
115123
"&",

0 commit comments

Comments
 (0)