Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useEffect missing dependency warning with ref in custom hook

In React Typescript with the exhaustive-deps rule enabled, when I define a ref and use that inside of an effect, the linter is fine with it:

const stringRef: RefObject<string> = useRef("Hello World!");
  
useEffect(() => {
  console.log(stringRef.current);
}, []) // no warning, the linter detects that I'm using a ref

However, when I put the effect inside of a custom hook, the linter complains that I should include the ref inside of the dependency array:

const stringRef: RefObject<string> = useRef("Hello World!");
  
useCustomHook(stringRef);

// in another-file.ts
const useCustomHook = (ref: RefObject<string>) => {
  useEffect(() => {
    console.log(ref.current);
  }, []) // ESLint: React Hook useEffect has a missing dependency: 'ref'. Either include it or remove the dependency array.(react-hooks/exhaustive-deps)
}

Semantically, nothing changed, however, the linter doesn't recognize that ref is a RefObject (even though I typed it as such).

The big question now is: How can I make the linter know that the given dependency doesn't need to be included in the dependency array without suppressing the warning?

For me, it's a major drawback that this is not possible, because I can't convert my effects into custom hooks without the linter complaining.

Thanks for your help.

like image 744
Boris Pöhland Avatar asked Feb 10 '21 11:02

Boris Pöhland


People also ask

How do I fix React hook useEffect has missing dependencies?

The warning "React Hook useEffect has a missing dependency" occurs when the useEffect hook makes use of a variable or function that we haven't included in its dependencies array. To solve the error, disable the rule for a line or move the variable inside the useEffect hook.

Can we use ref as dependency in useEffect?

useEffect has an unnecessary dependency: 'log'. aren't valid dependencies because mutating them doesn't re-render the component. This is because even if I did reassign that log variable to something else at some point, React wouldn't know about it so you'd end up with a stale side-effect anyway.

Can I use useEffect inside a hook?

Placing useEffect inside the component lets us access the count state variable (or any props) right from the effect. We don't need a special API to read it — it's already in the function scope. Hooks embrace JavaScript closures and avoid introducing React-specific APIs where JavaScript already provides a solution.

Can we use useRef in useEffect?

In the useEffect , we are updating the useRef current value each time the inputValue is updated by entering text into the input field.


1 Answers

You can't configure it out of the box.

The linter (eslint) is a static code analyzer. It only analyzes text patterns without compiling the code, i.e it doesn't know the "meaning" of what is written.

For example, it sees the "use***()" pattern and believes its a custom hook, then it verifies it with Rules of Hooks patterns like not having such text in if statement.

See for yourself:

Reminder: Custom hook is a function with 'use' prefix and a function which uses hooks.

// NOT A CUSTOM HOOK, just a function with 'use' prefix
const useConsole = () => console.log("hello");

// Normal function
const logHello = () => console.log("hello2");

const Component = () => {
  if (true) {
    // Warning - React hook is called conditionally
    useConsole();

    // OK
    logHello();
  }
  return <>Example</>;
};

Edit Eslint Example

But, you always can propose a custom rule to identify RefObject<string> and useEffect in same scope.

From the Typescript compiler side, it doesn't violate anything as the use case matches the useEffect type.

like image 132
Dennis Vash Avatar answered Dec 10 '22 13:12

Dennis Vash