title: Avoid infinite loop in custom hook
body: <p>I have created the following custom hook to simplify the usage of timeouts inside my application:</p>
  <pre><code>export const useTimer = () =&gt; {
    const [timer, setTimerObject] = useState&lt;ReturnType&lt;typeof setTimeout&gt; | null&gt;(null)
    
    //Function to set a new timer. If a timer is already present it is
    //canceled and substituted (useEffect)
    function setTimer(callback:(...args:any[])=&gt;void,ms:number){
      setTimerObject(setTimeout(callback,ms))
    }
  
    //Function to clear the timer (if there's one)
    function clearTimer(){
      if(timer) clearTimeout(timer);
      setTimerObject(null);
    }
  
    //shouldComponentUpdate: delete previous timer if a new timer is issued
    //work also as componentWillUnmount
    useEffect(() =&gt; {
      return () =&gt; {
        if (timer) clearTimeout(timer)
      }
    }, [timer])
  
    return ({
      setTimer,
      clearTimer
    })
  }
  </code></pre>
  <p>However, when I call it inside a useEffect statement, since I have to put timer inside the &quot;dependencies&quot; of the useEffect method, it generates an infinite loop. This is a behaviour I expect somehow, since setting the state will cause the component to &quot;reload&quot; and, as a consequence, useEffect is triggered again (causing the infinite loop). However, by searching online I couldn't find a way to avoid this behavior inside my Hook. For code clarity I want my hook to behaves similarly to useHistory hook. There is a way to edit my hook to avoid infinite loops? (Goal: avoid timer instance being change at every setState)</p>
  <p>Here is how the hook is called:</p>
  <pre><code>const timer = useTimer();
  
   useEffect(() =&gt; {
      if (showError===null) { //Just a random condition to
        setShowError(&quot;My error&quot;);
        timer.setTimer(() =&gt; setShowError(null), 2000)
      }
    }, [timer, showError])
  
  </code></pre>