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
Extract duplicate code between prop-types and no-unused-prop-types #1 #1536
Conversation
…-types and no-unused-prop-types have the same
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.
Just in the beginning, I'm a little concerned about the conflation of "is in a lifecycle method" with "is in the constructor" - could we start by keeping those separate, so the refactor is more 1-to-1?
lib/rules/no-unused-prop-types.js
Outdated
@@ -1058,7 +989,7 @@ module.exports = { | |||
ObjectPattern: function(node) { | |||
// If the object pattern is a destructured props object in a lifecycle | |||
// method -- mark it for used props. | |||
if (isNodeALifeCycleMethod(node.parent.parent)) { | |||
if (astUtil.inLifeCycleMethod(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.
is this necessarily equivalent? context.getScope()
won't be the same as node.parent.parent
, necessarily.
Thanks for feedback. I'm at a conference for the next 2 days, but I will make "is in constructor" separately and deeper investigate the differences |
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.
LGTM! For posterity, could you reply to my comments with a link to the lines of code for the test cases in question?
const genericDestructuring = | ||
isPropAttributeName(node) && ( | ||
utils.getParentStatelessComponent() || | ||
astUtil.inConstructor(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.
which test case exposes this missing inConstructor check?
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.
Note that the old isInLifeCycleMethod
function already was checking whether we are in constructor: node.kind === 'constructor'
. Now it is split into inConstructor
and inLifecycleMethod
so the code is the same between this rule and prop-types
.
In this case, the following two tests will fail when removing this line:
@@ -992,7 +928,8 @@ module.exports = { | |||
// let {firstname} = props | |||
const statelessDestructuring = destructuring && isPropAttributeName(node) && ( | |||
utils.getParentStatelessComponent() || | |||
isInLifeCycleMethod(node) | |||
astUtil.inConstructor(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.
also here, which test case exposes the need for this check?
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.
Same as above: Note that the old isInLifeCycleMethod
function already was checking whether we are in constructor: node.kind === 'constructor'
. Now it is split into inConstructor
and inLifecycleMethod
so the code is the same between this rule and prop-types.
However, this case seems to be untested. 😞 In master we can remove this whole block and the tests still pass.
&& ( utils.getParentStatelessComponent() || isInLifeCycleMethod(node))
@@ -1058,7 +995,7 @@ module.exports = { | |||
ObjectPattern: function(node) { | |||
// If the object pattern is a destructured props object in a lifecycle | |||
// method -- mark it for used props. | |||
if (isNodeALifeCycleMethod(node.parent.parent)) { | |||
if (astUtil.inConstructor(context) || astUtil.inLifeCycleMethod(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.
also 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.
Same as above.
Fails when removing inConstructor:
When removing the inLifecycleMethod
then 5 tests fail (2 for componentWillReceiveProps
, 1 for shouldComponentUpdate
and 2 for componentDidUpdate
)
I suppose that we can also test https://reactjs.org/docs/react-component.html#componentwillupdate which also has nextProps
as the first argument.
@@ -967,7 +942,7 @@ module.exports = { | |||
const directDestructuring = | |||
destructuring && | |||
PROPS_REGEX.test(node.init.name) && | |||
(utils.getParentStatelessComponent() || inConstructor() || inComponentWillReceiveProps()) |
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, which test cases warrant this change from just checking willReceiveProps, to checking all the lifecycle methods?
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 is missing tests! Indeed we will now check more cases than just componentWillReceiveProps
@jseminck @alexzherdev is this PR still useful, now that #1911 and friends have landed? |
It seems like what this PR contains has been achieved in spirit: there is now a single place that defines |
Are there test cases here we could salvage? |
Follow-up for: #1526
Basically in
prop-types
andno-unused-prop-types
there is quite a bit of duplicate code. I tried to do a HUGE refactoring to remove a lot of it but it turned out... well... not good 😄 So maybe smaller PRs is a better idea.Basically made the "are we in a lifecycle method" detection similar between
prop-types
andno-unused-prop-types
. Both rules were doing it differently but the results were the same. There was also duplicated methods likeinComponentWillReceiveProps
.There should be some new cases detected now, e.g. in
prop-types
rule:nextProps
should be considered not only forcomponentWillReceiveProps
, but also forshouldComponentUpdate
.On that note, I noticed that
prevProps
is not supported forprop-types
rule, with a lifecycle method ofcomponentDidUpdate
for example. There's some further refactoring needed to align the two rules more to get that properly working which I'd like to tackle in a PR after this.