[react-hooks/exhaustive-deps] should have special case for props callbacks
See original GitHub issuereact-hooks/exhaustive-deps
attempts to be 100% accurate, and flags the following:
const c = useCallback((value: number) => {
props.onChange(value);
}, [props.onChange]); // <-- ERROR: Should be [props]
It helpfully recommends that we should do this:
const {
onChange
} = props;
const c = useCallback((value: number) => {
onChange(value);
}, [onChange]);
Unfortunately, I can’t bring myself to actually write my code this way. It adds pointless boilerplate code, makes my IDE “find usages” feature on my props send me through another level of indirection i have to follow, and i have this ugly object destructure inside every react component I write only for the callback props that is plain ugly noise.
I’ve been using this technique lately:
useCallback((value: number) => {
props.onChange.call(null, value);
}, [props.onChange]); // <-- now the linter is happy!
Which is a bit better, but still ugly, and sadly the autocomplete experience for the call arguments is much worse.
I understand that if I were to write something like car.drive()
then the linter would be correct that I should depend on car
since car
is being passed as this
to drive, and car
might change.
But “props” specifically is different. No matter how hard I try, I cannot think of a legitimate case where someone would set a prop callback such that it is expecting the actual props as the this
argument. It makes no sense, and all of the official react documentation explain how you should use “bind” or whatever so that you have a locked-down this
(if this
is even needed at all). And the react team apparently agrees with me here, because this very lint rule suggests to destructure the prop, which would anyway break any such code that expects to have props
passed back as this
!
Recommendation: the lint rule should treat any function call of the form props.xxx(...)
such that the expected dependency is props.xxx
(instead of props
). Just to be clear: this should only be done specifically for props
, any other “method” style function call on an object other than props
should continue to be linted in the current way.
Thank you
Issue Analytics
- State:
- Created 3 years ago
- Comments:11 (3 by maintainers)
Destructuring works fairly poorly if your props are a disciminated union, eg:
Destructuring
props
breaks the discriminating union.This is a rare enough usecase for me personally that I’m fine with disabling the lint rule, but I’d be interested to know if anyone has a better solution
… I mean, you could do
But with it ends up being way too much repetition for my tastes