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

[eslint] strip tailing property in assignments #16784

Merged
merged 2 commits into from
Apr 4, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,16 @@ const tests = {
}
`,
},
{
code: normalizeIndent`
function MyComponent(props) {
let foo = {}
useEffect(() => {
foo.bar.baz = 43;
}, [foo.bar]);
}
`,
},
{
// Valid because we assign ref.current
// ourselves. Therefore it's likely not
Expand Down Expand Up @@ -6395,6 +6405,39 @@ const tests = {
// Keep this until major IDEs and VS Code FB ESLint plugin support Suggestions API.
options: [{enableDangerousAutofixThisMayCauseInfiniteLoops: true}],
},
{
code: normalizeIndent`
function MyComponent(props) {
let foo = {}
useEffect(() => {
foo.bar.baz = 43;
props.foo.bar.baz = 1;
}, []);
}
`,
errors: [
{
message:
"React Hook useEffect has missing dependencies: 'foo.bar' and 'props.foo.bar'. " +
'Either include them or remove the dependency array.',
suggestions: [
{
desc:
'Update the dependencies array to be: [foo.bar, props.foo.bar]',
output: normalizeIndent`
function MyComponent(props) {
let foo = {}
useEffect(() => {
foo.bar.baz = 43;
props.foo.bar.baz = 1;
}, [foo.bar, props.foo.bar]);
}
`,
},
],
},
],
},
],
};

Expand Down
19 changes: 19 additions & 0 deletions packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,25 @@ function getDependency(node) {
)
) {
return getDependency(node.parent);
} else {
return stripTailingPropInAssignment(node);
Copy link
Collaborator

Choose a reason for hiding this comment

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

What makes you think it's an assignment in this branch? Can we make it more specific and throw on something unexpected?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

😅 tryStrippingTrailingPropsInAssigment could have been a better choice. I'm trying to enumerate all cases and confused by a test:

function MyComponent(props) {
  useEffect(() => {
    if (props.foo.onChange) {
      props.foo.onChange();
    }
  }, []);
}

Why is props.foo a proper dependency? Why not props.foo.onChange?

}
}

/**
* Assuming () means the passed/returned node:
* (props) => (props)
* (props.foo) => (props.foo)
* (props.foo.bar) = X => (props.foo).bar = X
* (props.foo.bar.baz) = X => (props.foo.bar).baz
*/
function stripTailingPropInAssignment(node) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just inline in this function into the parent one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👌

if (
node.type === 'MemberExpression' &&
node.parent &&
node.parent.type === 'AssignmentExpression'
) {
return node.object;
} else {
return node;
}
Expand Down