react icon indicating copy to clipboard operation
react copied to clipboard

Bug: react-hooks/exhaustive-deps false positive when use function with generic type variable in useEffect

Open RThong opened this issue 2 years ago • 2 comments

React version: 18.2.0

Steps To Reproduce

  1. use function with generic type in useEffect

code example:

function useBug<T>(val: T) {
  const ref = useRef<T>(val)

  const fn = () => {
    const temp: T = ref.current // <-- if remove the generic type will be ok
  }

  useEffect(() => {
    fn()
  }, []) // <-- ESLint error: React Hook useEffect has a missing dependency: 'fn'.
}

package version:

npmPackages:
    @typescript-eslint/eslint-plugin: ^5.35.1 => 5.35.1 
    @typescript-eslint/parser: ^5.35.1 => 5.35.1 
    @typescript-eslint/scope-manager:  5.35.1 
    @typescript-eslint/type-utils:  5.35.1 
    @typescript-eslint/types:  5.35.1 
    @typescript-eslint/typescript-estree:  5.35.1 
    @typescript-eslint/utils:  5.35.1 
    @typescript-eslint/visitor-keys:  5.35.1 
    eslint: ^8.23.0 => 8.23.0 
    eslint-plugin-react-hooks: ^4.6.0 => 4.6.0 

relevant: #20395

The current behavior

React Hook useEffect has a missing dependency: 'fn'. Either include it or remove the dependency array.

The expected behavior

No missing dependencies reported.

RThong avatar Aug 27 '22 04:08 RThong

Had this bug too in my application

merhmood avatar Aug 27 '22 05:08 merhmood

But fn is missing. I don't get any different behavior when removing T.

What is producing a false-positive is

 useEffect(() => {
    const fn = () => {
      const temp: T = ref.current
    }
    fn()
  }, []) // <-- ESLint error: React Hook useEffect has a missing dependency: 'T'.

which needs fixing

eps1lon avatar Aug 31 '22 07:08 eps1lon

Another solution

function useBug<T>(val: T) {
  const ref = useRef<T>(val)

  const fn = useCallback(
    () => {
    const temp: T = ref.current // <-- if remove the generic type will be ok
    },
    [ref],
  )

  useEffect(() => {
    fn()
  }, [fn]) // <-- ESLint error: React Hook useEffect has a missing dependency: 'fn'.
}

albrimpaqarizi avatar Sep 18 '22 15:09 albrimpaqarizi

Here's a better reproducible example:

Edit compassionate-shockley-fbr2gd

import { useEffect, useState } from "react";
import "./styles.css";

function useTypedState<StateObject>(defaultValue: StateObject) {
  const [val, setVal] = useState<StateObject>(defaultValue);

  useEffect(() => {
    console.log(val as StateObject);
  }, [val]);
/*
      ^^^
      React Hook useEffect has a missing dependency: 'StateObject'.
      Either include it or remove the dependency array. (react-hooks/exhaustive-deps)eslint
*/
  return [val, setVal] as const;
}

export default function App() {
  const [count, setCount] = useTypedState<number>(0);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={() => setCount((c) => c + 1)}>{count}</button>
    </div>
  );
}

bogas04 avatar Feb 06 '23 18:02 bogas04