Skip to content
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] add no-unused-class-component-methods #2239

Merged
merged 1 commit into from Sep 30, 2021

Conversation

pawelnvk
Copy link
Contributor

@pawelnvk pawelnvk commented Apr 13, 2019

Display errors in case class component contains unused methods.

Fixes #2166.

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this is a great start. Let's add a lot more test cases tho :-)

// Rule Definition
// ------------------------------------------------------------------------------

const internalMethods = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about unused static methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be concerned about static methods? They doesn't seem to be closely connected to component. I feel that static methods could be used outside of component and in that case it would be harder to determine if method is used..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a react component, yes - it's not meant to be used as a class.

(An instance method could also be used outside of the component)

Perhaps maybe an option to control checking of static methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be a good idea. I'll try to tackle it after basic version.

lib/rules/no-unused-class-component-methods.js Outdated Show resolved Hide resolved
const isMethod = node.type === 'MethodDefinition';
const isArrowFunction = (
node.type === 'ClassProperty' &&
node.value.type === 'ArrowFunctionExpression'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about async functions, async arrow functions, generators, and async generators?

class Foo extends React.Component {
action() {}
componentDidMount() {
const action = this.action;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about use by object destructuring?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping on this one

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pawelnvk
Copy link
Contributor Author

Thanks for feedback. Currently I'm taking some time off, but I'll definitely get back to it next week. I'm super excited about it!

@ha404
Copy link

ha404 commented May 3, 2019

Would this also account for functional components?

@golopot
Copy link
Contributor

golopot commented May 3, 2019

@ha404 It shouldn't. no-unused-vars should suffice in the case of functional components.

@ha404
Copy link

ha404 commented May 3, 2019

@golopot but you can add static properties to functional components too.

const SomeComponent = () => ...

SomeComponent.propTypes = ...
SomeComponent.anythingYouWant = ...

@Kiwka
Copy link

Kiwka commented Aug 12, 2019

Is there anything I can do to help to get this to mergeable state?

@ljharb
Copy link
Member

ljharb commented Aug 15, 2019

@Kiwka if you post a link here to a branch that addresses the review comments and test failures here (please do NOT create a new PR) then I can pull in your commits, and we can definitely get this in.

@valtido
Copy link

valtido commented Aug 22, 2019

Looks good, can we look at those tests, please? desperado for this... :) (y)

@meowtec

This comment has been minimized.

@ljharb

This comment has been minimized.

@meowtec

This comment has been minimized.

@ljharb

This comment has been minimized.

@meowtec

This comment has been minimized.

@ljharb

This comment has been minimized.

@meowtec

This comment has been minimized.

{
code: `
class Foo extends React.Component {
property = {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it valid?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it also check unused property?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea; the rule should check both properties and methods.

@ljharb

This comment has been minimized.

@meowtec
Copy link
Contributor

meowtec commented Sep 20, 2019

Still in progress?

@ljharb
Copy link
Member

ljharb commented Oct 8, 2019

ping @pawelnvk

case 'ClassProperty':
case 'JSXAttribute':
case 'MethodDefinition':
getThisExpressions(subnode.value);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using the Object switch methodology rather than an actual switch, in my view, it's a lot faster than the switch.

See this link for a reference.
https://stackoverflow.com/questions/37730199/switch-vs-object-lookup-performance-since-jsperf-is-down

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Faster or not, it's always cleaner :-)

@meowtec
Copy link
Contributor

meowtec commented Oct 21, 2019

It seams that this PR has been abandoned.

I have (re)written this rule with another implementation and use it in our project which has over 100k lines of code.

see here https://github.com/meowtec/eslint-plugin-react-ext/blob/master/lib/rules/no-unused-class-property.js

@ljharb
Copy link
Member

ljharb commented Oct 22, 2019

@meowtec if you'd be able to make those changes in a branch on a fork - not a PR - then I can look into pulling them into this PR.

@meowtec
Copy link
Contributor

meowtec commented Oct 22, 2019

@ljharb My branch is at https://github.com/meowtec/eslint-plugin-react/tree/unused-component-methods-improve

What are different:

  • The new implementation inspired by no-unused-state.
  • Check both properties and methods.
  • Remove the support for the legacy ES5 style React.createClass. If necessary I will add it back.
  • Static methods are just ignored.
  • More test cases and bugfix.

@pawelnvk Please take a look because I am not sure if any important things was missing.

ref: #2239 (comment)

@ljharb
Copy link
Member

ljharb commented Nov 29, 2019

Yes, please add createClass support back; we'll be supporting it for the foreseeable future.

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add tests for state = {} and ensure that unused state is ignored.

}
```

The following patterns are **not** considered warnings:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's add some unused static methods here, so it's clear.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @meowtec

should all static methods be list here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there more than one? Either way we'd only need at least one as an example.

class Foo extends React.Component {
action() {}
componentDidMount() {
const action = this.action;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping on this one

Copy link
Contributor

@meowtec meowtec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please add createClass support back; we'll be supporting it for the foreseeable future.

https://github.com/meowtec/eslint-plugin-react/tree/unused-component-methods

  • add createReactClass back
  • ignore unused state

return;
}

switch (subnode.type) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These codes look verbose and many cases were lost, such as BinaryExpression arguments ArrayExpression, ObjectExpression, etc.

case 'ClassProperty':
case 'JSXAttribute':
case 'MethodDefinition':
getThisExpressions(subnode.value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subnode.value could be null so it will throw with error at the next switch (subnode.type).

eg:

<button disabled />

class Foo extends React.Component {
  a;
}

Fixed and added some test cases: meowtec@dd88dc1

getThisExpressions(subnode.init);
break;
case 'MemberExpression':
if (subnode.object.type !== 'ThisExpression') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should exclude the computed property:

class Foo extends React.Component {
  handleClick() {}
  render() {
    return <button onClick={this[handleClick]}>Text</button>;
  }
}

@jakeleventhal
Copy link
Contributor

Bumping

@ljharb
Copy link
Member

ljharb commented Aug 9, 2021

@pawelnvk are you still interested in landing this PR? if so, it could use a rebase and there's some review comments to address :-)

@ljharb ljharb marked this pull request as draft August 9, 2021 21:03
@jakeleventhal
Copy link
Contributor

@pawelnvk are you going to do this?
If not, I might do it @ljharb

@ljharb
Copy link
Member

ljharb commented Sep 14, 2021

@jakeleventhal that'd be great! however, please do NOT open a new PR; please comment here with a link to your branch, and I'll pull in the changes.

Co-authored-by: meowtec <bertonzh@gmail.com>
Co-authored-by: Jake Leventhal <jakeleventhal@me.com>
@ljharb
Copy link
Member

ljharb commented Sep 16, 2021

@jakeleventhal thanks! Pulling it in now. I do note that it's still missing support for the static getDerivedStateFromProps method.

@ljharb ljharb force-pushed the unused-component-methods branch 2 times, most recently from e51f8d7 to 7114353 Compare September 16, 2021 22:54
@ljharb ljharb changed the title [Feat] - Detect unused class component method [New] add no-unused-class-component-methods Sep 16, 2021
@codecov-commenter
Copy link

codecov-commenter commented Sep 16, 2021

Codecov Report

Merging #2239 (7114353) into master (9c1aee5) will increase coverage by 0.00%.
The diff coverage is 97.84%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2239   +/-   ##
=======================================
  Coverage   97.43%   97.44%           
=======================================
  Files         111      112    +1     
  Lines        7529     7622   +93     
  Branches     2769     2798   +29     
=======================================
+ Hits         7336     7427   +91     
- Misses        193      195    +2     
Impacted Files Coverage Δ
index.js 100.00% <ø> (ø)
lib/rules/no-unused-class-component-methods.js 97.84% <97.84%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9c1aee5...7114353. Read the comment docs.

@jakeleventhal
Copy link
Contributor

@ljharb im a bit unfamiliar with this repo. do you think you could just take this over since you're pulling in the change anyway? i would appreciate it

@jakeleventhal
Copy link
Contributor

@ljharb also, does this cover hooks?

@jakeleventhal
Copy link
Contributor

@ljharb bump

@ljharb
Copy link
Member

ljharb commented Sep 26, 2021

Sure, I can try to add it.

No, this doesn't cover hooks; the rule only has to do with class components. SFCs don't have methods.

@jakeleventhal
Copy link
Contributor

@ljharb okay, thank you. I will leave it to you to finish then i suppose

@ljharb ljharb force-pushed the unused-component-methods branch 2 times, most recently from 08a6f69 to 1371f71 Compare September 30, 2021 06:20
@ljharb ljharb marked this pull request as ready for review September 30, 2021 06:20
@ljharb ljharb merged commit 1371f71 into jsx-eslint:master Sep 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

react/no-unused-class-comp-methods
9 participants