-
Notifications
You must be signed in to change notification settings - Fork 46.7k
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
Feature proposal(eslint-react-hooks): don't require empty dependency useCallback in another dependency array #19217
Comments
This looks like a substantial change being proposed. 😄 Changes like this should go through our RFC process: The RFC process is a great opportunity to get more eyeballs on your proposal before it becomes a part of a released version of React. Quite often, even proposals that seem "obvious" can be significantly improved once a wider group of interested people have a chance to weigh in. The RFC process can also be helpful to encourage discussions about a proposed feature as it is being designed, and incorporate important constraints into the design while it's easier to change, before the design has been fully implemented. |
Admittedly I skimmed this pretty quickly, saw that you were proposing a change to the dependencies array, and closed it with a canned response. If I had scanned more carefully I probably would have left it open for discussion. My apologies. (I don't think it's quite the same as #19125 or I would suggest leaving it closed as a duplicate.) The updater function returned by |
@bvaughn no problem, thanks for reopening, I didn't really know the language to explain it in the right terms (stable vs unstable) so I can see how it's an easy mistake to make. |
No prob. To give you a little more insight, there are only ~6 core contributors to this repo right now and we're spread pretty thin. If you feel strongly about this issue, you'd probably have a lot better luck championing it through by submitting a PR (with tests!) 😄 |
Hi, thanks for opening the issue. I have a similar (but not exactly the same) when I use values from 3rd party libraries that are guarantee to be stable but the lint doesn't know about them (like "useState", but from other libraries). So basically I'm seeing there are 2 cases:
For starting, is it ok to PR to address the 1st use case first? I mean allow additional values to the knownStableValues array? I think it's simpler. I don't have experience working with linter so I don't really know how much is needed to implement (2) or will it have performance concerns |
The problem with making it configurable is that as a result, each library will recommend additions to the configuration. That's bad because it means everybody has to change their configs and defaults don't work. It has a rippling effect on the ecosystem. Instead, the solution is to simply keep these dependencies in the array. If they are truly stable, this will not cause any problems. |
Why |
We might have somewhat different definitions of "break". If There are other solutions if you really don't want that event to be re-attached (such as using refs). But it's hard to say why in this example it would be important. Adding and removing event handlers is extremely cheap. |
I guess because the function needs access to a ref maybe
Thank you. I understand that's bad in the long term. I'm glad to put them all in the dependencies array now |
@gaearon there were some issues in my example and I did since find a better pattern with fresher eyes (it had been a long day). I actually edited it from the erroneous (which would have done bad things if useEffect(() => {
if (mouseDown) {
document.addEventListener('mousemove', onMouseMove);
document.addEventListener('mouseup', onMouseUp);
} else {
document.removeEventListener('mousemove', onMouseMove);
document.removeEventListener('mouseup', onMouseUp);
}
}, [mouseDown, onMouseDown, onMouseUp]); That prompted me to ask the original question. The example in my other comment is actually OK now and doesn't depend upon values being stable at all.
It's entirely unnecessary for Regardless that I was doing the wrong thing in my example (which I since edited, sorry for the confusion) someone might find it useful, is there anything wrong with marking something provably stable as stable if it helps catch errors ahead of time? |
I don't think we want to do this. The problem is, eventually you might want to add some dependency to that callback. Then it's confusing if that starts showing up as an error everywhere that callback was used (rather than in a single place). It really doesn't hurt to include it, so you might as well include it from the beginning. |
Consider the following:
Above the
useEffect()
will complain that it didn't receiveonMouseMove
andonMouseUp
in its dependency array and it's correct. But it could be smarter, because they were all defined byuseCallback(() => {}, [])
meaning they will all remain the same value throughout the lifetime of this component.Given this information I could write
To satisfy the linter and that would work but only because I know they were defined by
useCallback(() => {}, [])
. If someone were to change the dependency array foronMouseMove
oronMouseUp
this would now break (the event listeners won't be removed and readded ifonMouseMove
changes for instance), but the linter will be happy.However if I was able to specify it like I did in the first example it is the same as saying, this works as long as these specific variables don't change, if someone unwittingly changes the dependency array of
onMouseMove
the linter would shout at them again and they would have to rewrite this into something more flexible.This is similar to the way
useCallback
doesn't complain about my usage ofsetMouseDown
as it knows it can't change.The text was updated successfully, but these errors were encountered: