-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[New Rule] prefer-function-component #3040
base: master
Are you sure you want to change the base?
[New Rule] prefer-function-component #3040
Conversation
#2860 doesn't have a "help wanted" or "accepted" label on it - I continue to be unconvinced this is actually a good rule to have. Some things must be class components, and other things are more clear/better as class components; I don't think a lint rule is naunced enough to be appropriate. That said, I did ask you to open the PR, so I'll give it a good faith review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if perhaps this could be a more generic "prefer-component-style" rule, that can be used to force class components or force function components?
Since the addition of hooks, it has been possible to write stateful React components | ||
using only functions. Mixing both class and function components in a code base adds unnecessary hurdles for sharing reusable logic. | ||
|
||
By default, class components that use `componentDidCatch` are enabled because there is currently no hook alternative for React. This option is configurable via `allowComponentDidCatch`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm not clear on why this is an option. A class component that's an error boundary can never be a functional component (pending changes from React itself), so there'd never be any value in this rule warning on it. I think that this option shouldn't be an option, it should just be hardcoded to true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many codebases I've seen don't implement error boundaries from scratch in their code base, instead they import library solutions that use error boundaries internally. I made this configurable (though with the default value of true
so most clients can ignore it) for clients who want all class component usage to be flagged. This also provides a migration path should React release functional component error boundaries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, Preact does offer functional error boundaries via a hook, so this would be valuable for those users.
suggestion: false, | ||
url: docsUrl('prefer-function-component') | ||
}, | ||
fixable: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason this rule isn't fixable?
Any component with a constructor body or class methods, of course, couldn't be fixable, but the example in the readme could.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partially fixable seemed odd to me on first thought, but the same logic as used by prefer-stateless-function could be used here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of rules are partially fixable; obv it's ideal when things are fully fixable tho.
Actually wait, I'd forgotten about prefer-stateless-function. How is this rule different from that one? https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prefer-stateless-function.md
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think #2860 explains the difference well:
The prefer-stateless-function rule is not enough for this case, since it allows class components provided they have a state or additional methods (like handlers defined as a class methods). It is not possible to forbid the use of state altogether (you can disable setState, but defining state is still allowed, silencing prefer-stateless-function), and filtering class methods using eslint rules without interfering with other code is complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i see, so this is a stronger thing than that, where prefer-stateless-function pushes SFCs when possible, this rule would ban class components entirely in favor of hook-using SFCs. Gotcha.
Yeah that seems reasonable to me, the motivating intent here is to keep consistency in a code base. Looking at the recent work by the Relay team (and their close collaboration with the React team) and the React concurrent mode work my impression is that the longer term direction of React is going to be towards all function components, but that is speculative right now. |
I don't have any expectations here, just something to consider. This can always sit or be closed and reopened in the future. I just want things to be code complete (or close) while I have the time. |
Just wanted to add a voice of support for this approach. |
Just wanted to pop in to say I'd like to have this lint rule too. As pointed out elsewhere, the biggest value here is in enabling consistency across a codebase and the ability to reuse logic between components easily. In my case, another big use is to use these lint rules to gauge how well we are/are not doing in paying down tech debt over time on an old-ish codebase where we're about 50/50 on function components versus class components. Given the large-ish size of our org and codebase, this has to be automated via tooling so we can create dashboards/reports/etc. |
Does the |
No that rule enforces the function definition and the request here is to enforce function components instead of class components. It’s complementary but none overlapping. |
Agree with Tate. This rule, while useful, doesn't solve the issue of preventing the introduction of class components into a codebase. |
59af733
to
865ed16
Compare
069314a
to
181c68f
Compare
Looks like this PR has gone dormant. I also support the addition of this rule. It would be useful when managing a codebase whose contributors have different levels of familiarity with React, e.g., a mix of FE specialists and mid-stack or backend devs that are more used to class-heavy OO languages. Has anything changed from the maintainer's point of view over the last year? I feel like the greater community has almost fully abandoned classes. |
@robwierzbowski nope, nothing's changed there, and ErrorBoundary in particular still is required to be a class component. |
That's true. I believe this code allows error boundaries to remain class components. As you discussed above, whether this is hardcoded true or an option, the issue could be addressed. |
380e32c
to
51d342b
Compare
Adds a new rule to enforce the use of function components over class components. Related issue: #2860
Users wanting to try this lint rule today:
This functionality exists in eslint-plugin-react-prefer-function-component.
npm install eslint-plugin-react-prefer-function-component