Skip to content

Commit 1b61631

Browse files
authored
feat(lint): add noReactForwardRef rule (#7509)
1 parent 38d2098 commit 1b61631

File tree

28 files changed

+1706
-44
lines changed

28 files changed

+1706
-44
lines changed

.changeset/calm-stars-rhyme.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Added a new lint rule [`noReactForwardRef`](https://biomejs.dev/linter/rules/no-react-forward-ref/), which detects usages of `forwardRef` that is no longer needed and deprecated in React 19.
6+
7+
For example:
8+
9+
```jsx
10+
export const Component = forwardRef(function Component(props, ref) {
11+
return <div ref={ref} />;
12+
});
13+
```
14+
15+
will be fixed to:
16+
17+
```jsx
18+
export const Component = function Component({ ref, ...props }) {
19+
return <div ref={ref} />;
20+
};
21+
```
22+
23+
Note that the rule provides an unsafe fix, which may break the code. Don't forget to review the code after applying the fix.

crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rs

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_configuration/src/analyzer/linter/rules.rs

Lines changed: 64 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/biome_diagnostics_categories/src/categories.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ define_categories! {
173173
"lint/nursery/noNextAsyncClientComponent": "https://biomejs.dev/linter/rules/no-next-async-client-component",
174174
"lint/nursery/noNonNullAssertedOptionalChain": "https://biomejs.dev/linter/rules/no-non-null-asserted-optional-chain",
175175
"lint/nursery/noQwikUseVisibleTask": "https://biomejs.dev/linter/rules/no-qwik-use-visible-task",
176+
"lint/nursery/noReactForwardRef": "https://biomejs.dev/linter/rules/no-react-forward-ref",
176177
"lint/nursery/noSecrets": "https://biomejs.dev/linter/rules/no-secrets",
177178
"lint/nursery/noShadow": "https://biomejs.dev/linter/rules/no-shadow",
178179
"lint/nursery/noUnnecessaryConditions": "https://biomejs.dev/linter/rules/no-unnecessary-conditions",

crates/biome_js_analyze/src/lint/nursery.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub mod no_misused_promises;
1111
pub mod no_next_async_client_component;
1212
pub mod no_non_null_asserted_optional_chain;
1313
pub mod no_qwik_use_visible_task;
14+
pub mod no_react_forward_ref;
1415
pub mod no_secrets;
1516
pub mod no_shadow;
1617
pub mod no_unnecessary_conditions;
@@ -32,4 +33,4 @@ pub mod use_qwik_classlist;
3233
pub mod use_react_function_components;
3334
pub mod use_sorted_classes;
3435
pub mod use_vue_multi_word_component_names;
35-
declare_lint_group! { pub Nursery { name : "nursery" , rules : [self :: no_deprecated_imports :: NoDeprecatedImports , self :: no_floating_promises :: NoFloatingPromises , self :: no_import_cycles :: NoImportCycles , self :: no_jsx_literals :: NoJsxLiterals , self :: no_misused_promises :: NoMisusedPromises , self :: no_next_async_client_component :: NoNextAsyncClientComponent , self :: no_non_null_asserted_optional_chain :: NoNonNullAssertedOptionalChain , self :: no_qwik_use_visible_task :: NoQwikUseVisibleTask , self :: no_secrets :: NoSecrets , self :: no_shadow :: NoShadow , self :: no_unnecessary_conditions :: NoUnnecessaryConditions , self :: no_unresolved_imports :: NoUnresolvedImports , self :: no_unused_expressions :: NoUnusedExpressions , self :: no_useless_catch_binding :: NoUselessCatchBinding , self :: no_useless_undefined :: NoUselessUndefined , self :: no_vue_data_object_declaration :: NoVueDataObjectDeclaration , self :: no_vue_reserved_keys :: NoVueReservedKeys , self :: no_vue_reserved_props :: NoVueReservedProps , self :: use_anchor_href :: UseAnchorHref , self :: use_consistent_arrow_return :: UseConsistentArrowReturn , self :: use_consistent_type_definitions :: UseConsistentTypeDefinitions , self :: use_exhaustive_switch_cases :: UseExhaustiveSwitchCases , self :: use_explicit_type :: UseExplicitType , self :: use_image_size :: UseImageSize , self :: use_max_params :: UseMaxParams , self :: use_qwik_classlist :: UseQwikClasslist , self :: use_react_function_components :: UseReactFunctionComponents , self :: use_sorted_classes :: UseSortedClasses , self :: use_vue_multi_word_component_names :: UseVueMultiWordComponentNames ,] } }
36+
declare_lint_group! { pub Nursery { name : "nursery" , rules : [self :: no_deprecated_imports :: NoDeprecatedImports , self :: no_floating_promises :: NoFloatingPromises , self :: no_import_cycles :: NoImportCycles , self :: no_jsx_literals :: NoJsxLiterals , self :: no_misused_promises :: NoMisusedPromises , self :: no_next_async_client_component :: NoNextAsyncClientComponent , self :: no_non_null_asserted_optional_chain :: NoNonNullAssertedOptionalChain , self :: no_qwik_use_visible_task :: NoQwikUseVisibleTask , self :: no_react_forward_ref :: NoReactForwardRef , self :: no_secrets :: NoSecrets , self :: no_shadow :: NoShadow , self :: no_unnecessary_conditions :: NoUnnecessaryConditions , self :: no_unresolved_imports :: NoUnresolvedImports , self :: no_unused_expressions :: NoUnusedExpressions , self :: no_useless_catch_binding :: NoUselessCatchBinding , self :: no_useless_undefined :: NoUselessUndefined , self :: no_vue_data_object_declaration :: NoVueDataObjectDeclaration , self :: no_vue_reserved_keys :: NoVueReservedKeys , self :: no_vue_reserved_props :: NoVueReservedProps , self :: use_anchor_href :: UseAnchorHref , self :: use_consistent_arrow_return :: UseConsistentArrowReturn , self :: use_consistent_type_definitions :: UseConsistentTypeDefinitions , self :: use_exhaustive_switch_cases :: UseExhaustiveSwitchCases , self :: use_explicit_type :: UseExplicitType , self :: use_image_size :: UseImageSize , self :: use_max_params :: UseMaxParams , self :: use_qwik_classlist :: UseQwikClasslist , self :: use_react_function_components :: UseReactFunctionComponents , self :: use_sorted_classes :: UseSortedClasses , self :: use_vue_multi_word_component_names :: UseVueMultiWordComponentNames ,] } }

0 commit comments

Comments
 (0)