简体   繁体   中英

React, ESLint: eslint-plugin-react-hooks shows incorrect “missing dependency”

Assume you are using React and you are writing a custom hook useSomething that returns the identical same thing each time it is invoked for the same component.

const something = useSomething()

// useSomething() at time X  === useSomething() at time Y

If you now use this something value inside of a useEffect(() =>...) and you do not pass something as a dependency to the array of the second argument of useEffect then the linter will warn you:

React Hook useEffect has a missing dependency: 'something'. Either include it or remove the dependency array. (react-hooks/exhaustive-deps)

Of course ESLint cannot know that something will always stay identical (per component), but adding not-changing things like something to the dependency array of useEffect each time they are used is really annoying. Just deactivating react-hooks/exhaustive-deps does also not seem to be a good solution (nor using // eslint-disable-next-line react-hooks/exhaustive-deps ).

Is there a better solution than to add things like that unnecessarily to the dependency array of useEffect just to make the Linter happy?

Please find a simple demo here: https://codesandbox.io/s/sad-kowalevski-yfxcn [Edit: Please be aware that the problem is about the general pattern described above and not about this stupid little demo - the purpose of this demo is just to show the ESLint warning, nothing else]

[Edit] Please find an additional demo here: https://codesandbox.io/s/vibrant-tree-0cyn1

Here

https://github.com/facebook/react/issues/14920#issuecomment-471070149

for example you can read this:

If it truly is constant then specifying it in deps doesn't hurt. Such as the case where a setState function inside a custom Hook gets returned to your component, and then you call it from an effect. The lint rule isn't smart enough to understand indirection like this. But on the other hand, anyone can wrap that callback later before returning, and possibly reference another prop or state inside it. Then it won't be constant, And if you fail to handle those changes. you'll have nasty stale prop/state bugs. So specifying it is a better default.

So maybe just adding that never-changing values to the dependency array of useEffect may yet be the best solution. Nevertheless I hoped there would be something like a ESLint react-hooks configuration possibility to define a list of hook names which whose return values should be considered as static.

The example is a little contrived but I suspect you may wish to create a new useEffect block without this dependency.

If the store is not changing though I'd question why you'd wish to console log it time. If you wish to log it only on change then you'd add someStore to your dependency array. It really depends on what you're trying to achieve and your seperation of concerns.

I'd argue that if someStore is used as part of whatever logic is handled in this effect then it does belong in your dependency array.

You could also alternatively move const something = useSomething() into your effect and extract it as a custom hook link

useEffect(() => {
    console.log("Current state (may change)", someState);

  }, [someState]); 

useEffect(() => {
    console.log("Current store (will never change)", someStore);
  }); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM