5

When you call one of the "builtin" hook, the react-hooks/exhaustive-deps rule is smart enough to recognize that some return values are guaranteed by React to be invariant. This is the case for state updaters and dispatchers returned by useState and useReducer hooks.

In this first example, the call to useCallback does not need to list the state setter as a dependency:

export const Example1 = () => {
  const [date, setDate] = useState(new Date())

  const resetDate = useCallback(() => {
    setDate(new Date())
  }, []) // No need to list any dependency here. No eslint warning.

  return (
    <>
      Date: {date.toISOString()} <button onClick={resetDate}>Reset</button>
    </>
  )
}

But in the second example, where the setter is returned by a custom hook, it is required.

const useDateState = (initialValue: Date) => {
  return useState(initialValue)
}

export const Example2 = () => {
  const [date, setDate] = useDateState(new Date())

  const resetDate = useCallback(() => {
    setDate(new Date())
  }, []) // ESLint complains: React Hook useCallback has a missing dependency: 'setDate'. Either include it or remove the dependency array.

  return (
    <>
      Date: {date.toISOString()} <button onClick={resetDate}>Reset</button>
    </>
  )
}

Is there a way to tell the eslint rule that the setter returned by my custom hook will not change and that it does not need to list it as a dependency? This would help remove some code.

Note: I have read the React FAQ, this StackOverflow question and I understand that there is no performance cost to adding a dependency that will not change.

But since this behavior is available with the built-in hooks, I want to know if there is a way to get the same for a custom hook.

sarfata
  • 4,625
  • 4
  • 28
  • 36
  • See also this GitHub issue which discusses the same problem: https://github.com/reactjs/reactjs.org/issues/1889 – sarfata Jun 18 '20 at 18:14

0 Answers0