Skip to content

Commit 98510d2

Browse files
connorsheacamc314
andauthored
feat(linter): Implement react/prefer-function-component (oxc-project#19652)
This is based on the rule provided in [eslint-plugin-react-prefer-function-component](https://www.npmjs.com/package/eslint-plugin-react-prefer-function-component). This rule is [proposed for eslint-plugin-react](jsx-eslint/eslint-plugin-react#3040), but so far not merged. The goal of the rule is pretty simple. We want to discourage class components like this, as they are not used very often in modern React: ```jsx class Foo extends React.Component { render() { return <div>{this.props.foo}</div>; } } class Bar extends React.PureComponent { render() { return <div>{this.props.bar}</div>; } } ``` And encourage function components like this: ```jsx const Foo = function(props) { return <div>{props.foo}</div>; }; const Bar = ({ bar }) => <div>{bar}</div>; ``` - [Original Rule Source](https://github.com/tatethurston/eslint-plugin-react-prefer-function-component/blob/4682fae095307a73db6bda706ec53a61ad6bd60c/packages/eslint-plugin-react-prefer-function-component/src/prefer-function-component/index.ts) - [Original Rule Tests](https://github.com/tatethurston/eslint-plugin-react-prefer-function-component/blob/main/packages/eslint-plugin-react-prefer-function-component/src/prefer-function-component/index.test.ts) The original eslint-plugin-react plugin lacks a lint rule like this, which is very silly as it has one for preferring class components (which are notably [discouraged by React itself](https://react.dev/reference/react/Component) nowadays). It does have `prefer-stateless-functions`, however I would strongly recommend we mark that rule as unsupported in favor of this rule. If you look at [the tests for prefer-stateless-function](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/tests/lib/rules/prefer-stateless-function.js), you can see how lenient it is in allowing class components (anything with a method other than `render()` is allowed, basically). And it has the usual eslint-plugin-react smells of supporting things from many many many years ago. This rule is much more straight-forward, and generally a better implementation of the concept. We could, alternatively, implement this based on [this rule](https://www.eslint-react.xyz/docs/rules/no-class-component) from `@eslint-react/eslint-plugin` (different from eslint-plugin-react), however I generally prefer the `prefer-function-component` name and the `@eslint-react` rule was generally going to be more complex to implement. AI Disclosure: Generated with Claude Code w/ Opus 4.5, after prep work by me. Tested and reviewed by me. I created the rule via the rulegen tooling, then manually copied over the initial set of test cases myself. I then had Claude create the remaining tests from the original source code. From looking through the tests, I am confident in the quality/accuracy of the ported tests, and will be doing further testing via oxc-ecosystem-ci. Ecosystem CI run: https://github.com/oxc-project/oxc-ecosystem-ci/actions/runs/22334972119 Bsky for example. [main](https://github.com/oxc-project/oxc-ecosystem-ci/actions/runs/22331033071/job/64613773279): ``` Found 0 warnings and 78356 errors. Finished in 1.7s on 1553 files with 629 rules using 4 threads. ``` [this PR](https://github.com/oxc-project/oxc-ecosystem-ci/actions/runs/22334972119/job/64625880558): ``` Found 0 warnings and 78361 errors. Finished in 1.5s on 1553 files with 630 rules using 4 threads. ``` The 5 extra violations are due to this rule, and all 5 are correctly catching class component usage. In terms of performance, there's clearly no noticeable difference here, even on a React codebase of a decent size. --------- Co-authored-by: Cameron Clark <cameron.clark@hey.com>
1 parent 871f9d9 commit 98510d2

5 files changed

Lines changed: 1615 additions & 1 deletion

File tree

crates/oxc_linter/src/generated/rule_runner_impls.rs

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

crates/oxc_linter/src/generated/rules_enum.rs

Lines changed: 27 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_linter/src/rules.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ pub(crate) mod react {
431431
pub mod no_will_update_set_state;
432432
pub mod only_export_components;
433433
pub mod prefer_es6_class;
434+
pub mod prefer_function_component;
434435
pub mod react_in_jsx_scope;
435436
pub mod require_render_return;
436437
pub mod rules_of_hooks;

0 commit comments

Comments
 (0)