skip to Main Content

Given a simple hook function useFoo with a simple function foo.

When I use a function inside of useEffect, everything appears to function fine, but I get a waring from exhaustive-deps saying that function must be listed as a dependency.

When I add the function to the deps array it causes the effect to fire repeatedly or even continuously depending on the situation.

Why is foo not stable? Or how do I make the warning go away, and keep my code working properly?

const useFoo = () => {
  const foo = () => {
    return 'foo'
  }
  return {
    foo
  }
}

export default useFoo

Used in a control without dep

  useEffect(() => {
    console.log('i fire 2 times because of React.Strict')
  }, [])

Used in a control with dep

  useEffect(() => {
    console.log('i fire many times')
  }, [foo])

2

Answers


  1. Chosen as BEST ANSWER

    UseCallback needs to be added to the foo function to make it stable.

    const useFoo = () => {
      const foo = useCallback(() => {
        return 'foo'
      }, [])
      return {
        foo
      }
    }
    

  2. const useFoo = () => {
      const foo = () => { // <- this creates a new function every time the hook is called
        return 'foo'
      }
      return { // <- this creates a new object every time the hook is called
        foo
      }
    }```
    
    The function is completely stateless and independent of the enclosing hook. Consequently, it can be moved outside the hook so that only a single instance of it exists:
    
    

    const foo = () => {
    return ‘foo’
    }

    const useFoo = () => {
    return {
    foo
    }
    }

    
    Moving stateless and independent functions out of the hook is cleaner and cheaper than using yet another hook to cache the function instance (the function instances are still created when executing your hook, they are then simply discarded and ignored).
    
    You can do the same with the object literal, which doesn't depend on anything from the hook:
    
    
    

    const foo = () => {
    return ‘foo’
    }

    const fooObj = {
    foo
    }

    const useFoo = () => {
    return fooObj
    }

    
    But then the question becomes why do you have a hook in the first place if you don't use any hook functionality? Just call your `foo` function directly.
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search