Skip to content

Commit cfb85d7

Browse files
Add no-forward-ref rule (#7)
Since React 19, we no longer need forwardRef and can use simpler syntax. This rule reminds us not to use forwardRef.
1 parent ff0b124 commit cfb85d7

File tree

4 files changed

+45
-0
lines changed

4 files changed

+45
-0
lines changed

src/config/other.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const otherRules = {
1010
"@denis-sokolov/no-single-letter-generic-types": "error",
1111
"@denis-sokolov/no-todos": "error",
1212

13+
"@qawolf/no-forward-ref": "error",
1314
"@qawolf/no-utils": "error",
1415
"@qawolf/restrict-names": "error",
1516
"@qawolf/restrict-stop-propagation": "error",

src/rules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import importsConfigValid from "./imports-config-valid";
55
import importsPrefix from "./imports-prefix";
66
import maxLines from "./max-lines";
77
import noFloatingPromises from "./no-floating-promises";
8+
import noForwardRef from "./no-forward-ref";
89
import noUtils from "./no-utils";
910
import restrictNames from "./restrict-names";
1011
import restrictNewError from "./restrict-new-error";
@@ -22,4 +23,5 @@ export const rules = {
2223
"restrict-react-namespace": restrictReactNamespace,
2324
"restrict-stop-propagation": restrictStopPropagation,
2425
"no-floating-promises": noFloatingPromises,
26+
"no-forward-ref": noForwardRef,
2527
} satisfies Record<string, RuleDefinition>;

src/rules/no-forward-ref.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { valid, invalid } from "./tester";
2+
import rule from "./no-forward-ref";
3+
4+
valid(rule, "can import Ref", "import { type Ref } from 'react'");
5+
valid(rule, "can use ref prop in jsx", "<Component ref={ref} />");
6+
7+
invalid(
8+
rule,
9+
"can not import forwardRef",
10+
"import { forwardRef } from 'react'",
11+
);
12+
invalid(
13+
rule,
14+
"can not import type forwardRef",
15+
"import { type forwardRef } from 'react'",
16+
);
17+
18+
invalid(
19+
rule,
20+
"can not import forwardRef with other imports",
21+
"import { type Ref, forwardRef, useState } from 'react'",
22+
);
23+
24+
invalid(
25+
rule,
26+
"can not import ForwardedRef",
27+
"import { type ForwardedRef } from 'react'",
28+
);

src/rules/no-forward-ref.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineImportsRule } from "../imports";
2+
3+
export default defineImportsRule(function (details) {
4+
const { names, imported } = details;
5+
if (imported.type !== "other") return { allowed: true };
6+
if (!names.all.includes("forwardRef") && !names.all.includes("ForwardedRef"))
7+
return { allowed: true };
8+
9+
return {
10+
allowed: false,
11+
forbiddenNames: ["forwardRef", "ForwardedRef"],
12+
message: `Use the ref prop on your component instead. https://react.dev/blog/2024/12/05/react-19#ref-as-a-prop`,
13+
};
14+
});

0 commit comments

Comments
 (0)