-
Notifications
You must be signed in to change notification settings - Fork 49.2k
[ESLint] Deduplicate suggested dependencies #14982
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
Conversation
Details of bundled changes.Comparing: 02404d7...bff43db eslint-plugin-react-hooks
Generated by 🚫 dangerJS |
}, [props.foo.bar.baz]); | ||
} | ||
`, | ||
}, |
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.
Nice test! 👍
function MyComponent(props) { | ||
const fn = useCallback(() => { | ||
console.log(props.foo.bar.baz); | ||
}, [props.foo]); |
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 guess this is the right approach, since we kind of have to assume immutability for much of this stuff to work. Seems like it's at least possible that props.foo.bar.baz
was specified because foo
gets mutated, but I guess we just don't support that 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.
Yeah. (This was already the case before this PR btw.)
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.
Yeah, this particular before and after example just made me think about it more closely :)
output: ` | ||
function MyComponent(props) { | ||
useEffect(() => { | ||
if (props.onChange) { | ||
props.onChange(); | ||
} | ||
}, [props, props.onChange]); | ||
}, [props]); |
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.
Nice 👍
})); | ||
} | ||
|
||
// Alphabetize the suggestions, but only if deps were already alphabetized. |
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.
❤️
The previous algorithm was pretty ad-hoc which resulted in edge cases like when it suggested
[props, props.onChange]
when[props]
alone would suffice. This is a rewrite of it that instead maintains a data structure representing property chains. We mark the nodes that are required (i.e. used in the code), and then mark the nodes that are satisfied (i.e. specified in the dependency list).That lets us precisely calculate the minimal necessary deps. (However, for effects we still allow extraneous deps when they’re already specified.) It should also open the door to making the rule smarter in the future (e.g. we should be able to extend this logic to suggest a parent object if we use >5 its properties or similar).
See inline comments and new tests.