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
[destructuring-assignment] : new rule #1462
Conversation
|
||
## Rule Details | ||
|
||
By default rule is set to `always` enforce destructuring assignment. The following pattern is considered warning: |
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.
presumably we'd want the default to be "always" on all component types; releasing the rule with only SFC support means we couldn't default class and createClass components to "always" without a major release
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 am not sure about your major release concern. Would releasing only SFC support require a major release? What's the problem eith having to do a major release?
Irrespective of that I have only one use case for "other" component types as per issue #278 and I am not particularly keen about it. Are you? Maybe it would make sense to have this rule for SFC only?
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.
releasing only SFC support would be a minor.
Later releasing class-based component supported, defaulted to "ignore", would also be a minor.
However, later releasing class-based component supported, defaulted to "always", would be a major.
There's not a problem per se about releasing a major release, but it's always best to minimize breaking changes.
My use case for non-SFC components is that I want all this.props
, this.state
, and this.context
properties destructured at the top of every function that uses them (that also includes context
in SFCs).
It would be great if one rule could handle all of these cases - if not, I'd expect this rule to only ever handle SFCs (props and context), and a new rule to be added for "inside non-SFC functions".
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.
Ok, well in this case I can try to add the rest of the logic to this pr.
So both of the component types will enforce context
and props
. Class component will in addition enforce state
.
Config structure would be: { SFC: always/never/ignore, class: always/never/ignore}
(I don't like name class
is there a better term?)
default: { SFC: always, class: always }
there is also a nextProps, prevProps which I would ignore for now.
Does this make sense?
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 class
is probably the best name, unfortunately.
I agree ignoring next/prev props is fine for now, in SFCs, it'd be props
and context
, and in class-based and createClass components, it'd be this.props
and this.state
and this.context
.
if (relatedComponent && isStatelessFunctionUsage && options.SFC === 'always') { | ||
context.report({ | ||
node: node, | ||
message: 'Should use destructuring props assignment in SFC argument' |
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.
s/Should/Must/g
?
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.
hm, what do you mean?
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.
it's not that you should use it, it's that you must because of the rule
@ljharb , FYI, this is ready for 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.
What about things like:
class Foo extends React.Component {
render() { return this.foo(); }
foo() {
return this.props.children; // should be warned when "always"
}
}
if (isPropUsed && options.SFC === 'always') { | ||
context.report({ | ||
node: node, | ||
message: `Should use destructuring ${node.object.name} assignment` |
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 the word "must" here is better than "should"
if (classComponent) { | ||
handleClassUsage(node, classComponent); | ||
} | ||
} |
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.
can we also handle createClassComponents here?
753e3fb
to
1a5a9b6
Compare
@ljharb Ready for re-review
Two above examples are added to test cases. Changed |
In specifications, "should" means the implementation can choose not to comply; "must" means they are forced to comply. If the rule is enabled, they're being forced to comply :-) |
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.
Can we ensure every example case has a test for both "default", "explicit always", and "explicit never"? In particular, the createClass ones.
I'm also wondering if class-based components and createClass components should have separate configurability?
…destructuring assignment
I think that For example this test is invalid:
while this one is valid:
I would do it separately if it is a popular request. I added explicit always test cases (which match default ones). And few more tests for class components. Hope it covers everything. |
@ljharb , btw I am squashing any new commits I add. It may look the last commit was 8days ago but I just pushed the change. |
Yes, that's exactly what I'm expecting - if the user chooses "never", then they want |
@ljharb, this is ready for 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.
This still needs an option and documentation for createClass components.
@@ -0,0 +1,87 @@ | |||
# Enforce consostent usage of destructuring assignment of props, state and context (react/destructuring-assignment) | |||
|
|||
Rule can be set to either of `always`, `never`, `ignore` for `class` and `SFC` components. |
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.
this should probably mention createClass
components as well
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.
@ljharb, do you suggest createClass
as additional option? So it would be [SFC
, createClass
, class
]? If so can it be done as a separate PR? Right now class
option includes createClass
.
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.
Yes, I think they should be separate options - i think it'd be fine to add it in a separate PR, but I don't think this should be merged with class
handling both :-/
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.
hmmm, could you explain rationale behind that? To me this rule almost can be monolithic (cover all possible react components with a single setting). I can see the need for SFC vs Class components distinction, but not class vs createClass. What is the use case?
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.
For one, createClass components are often legacy, and legacy things need different rules. Mainly though, all three are actually distinct constructs - createClass components have different behavior than class-based components, in particular around auto-binding all the "instance" methods;
I think that it'd be fine to allow a string or an object option, where the string option is a single setting for all components - but the object option is intended to allow fine-grained control, so it's supposed to be not monolithic by design.
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 agree, technically if we are going to list component types, we should list them all. But even though it is very little code to be added to support the 3rd createClass
option, I am not very comfortable adding a special config option for a deprecated functionality. Additionally the difference in behaviour between class
and createClass
component doesn't seem to be related to what this rule is checking (in both props are referenced with this.props
right, or am I wrong?).
So seems like the single string option controlling all components is an acceptable solution for both of us and is common pattern across the library. I will update my pr shortly.
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.
@ljharb I added an incremental change to switch to a single string option so it might be easier to review.
|
||
Rule can be set to either of `always`, `never`, `ignore` for `class` and `SFC` components. | ||
```js | ||
"react/destructuring-assignment": [<enabled>, { "SFC": "always", "class": "always"}] |
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 here
module.exports = { | ||
meta: { | ||
docs: { | ||
description: 'Enforce consostent usage of destructuring assignment of props, state and context', |
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.
s/consostent/consistent
also, please use an Oxford comma after state
@DianaSuvorova, thanks for creating this rule - my team is looking forward to when this gets merged in :) |
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.
lol, that's one way to settle the debate :-p
this is fine; we can add more granular options for the 3 component kinds later :-)
@@ -0,0 +1,87 @@ | |||
# Enforce consostent usage of destructuring assignment of props, state and context (react/destructuring-assignment) |
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.
consostent → consistent, and please use an Oxford comma after "state"
@ljharb anything else is missing for this PR? |
@DianaSuvorova it seems like the changes were approved? |
@hendrikswan, yeah, but I don't have permissions to merge to master. |
On realized that after my comment.. I admire your perseverance!
…On Tue, 24 Oct 2017 at 5:34 PM DianaSuvorova ***@***.***> wrote:
@hendrikswan <https://github.com/hendrikswan>, yeah, but I don't have
permissions to merge to master.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#1462 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAQsNeAdBpZiscUk4C1L3ITfAXpwpovSks5svgOZgaJpZM4Psza7>
.
|
to enforce consistent usage of destructuring assignment closes #216, closes #556, closes #278