useTimeout

useTimeout

A custom React Hook that allows you to set a timeout and then clear or reset it.

Props

  • callback (function): The function to be called when the timeout expires.
  • delay (number): The delay in milliseconds for when the callback should be executed.

Return

  • reset (function): Resets the timeout and restarts the countdown.
  • clear (function): Clears the timeout and stops the countdown.

The Hook

useTimeout.ts
import { useCallback, useRef } from 'react'
import { useIsomorphicEffect } from '../useIsomorphicEffect'
 
export const useTimeout = (callback: () => void, delay: number) => {
  const callbackRef = useRef(callback)
  const timeoutRef = useRef<number | null>()
 
  useIsomorphicEffect(() => {
    callbackRef.current = callback
  }, [callback])
 
  const set = useCallback(() => {
    if (!delay && delay !== 0) {
      return
    }
 
    timeoutRef.current = setTimeout(() => callbackRef.current(), delay)
  }, [delay])
 
  const clear = useCallback(() => {
    timeoutRef.current && clearTimeout(timeoutRef.current)
  }, [])
 
  useIsomorphicEffect(() => {
    set()
    return clear()
  }, [delay, set, clear])
 
  const reset = useCallback(() => {
    clear()
    set()
  }, [clear, set])
 
  return { reset, clear }
}

Usage

UseTimeoutDemo.tsx
import React, { useState } from 'react'
import { useTimeout } from './useTimeout'
 
export const UseTimeoutDemo = () => {
  const [count, setCount] = useState(10)
  const { reset, clear } = useTimeout(() => setCount(0), 5000)
 
  return (
    <div>
      <div>{count}</div>
      <button onClick={() => setCount((c) => c + 1)}>Increment</button>
      <button onClick={clear}>Clear Timeout</button>
      <button onClick={reset}>Reset Timeout</button>
 
      <p>{count ? 'Timeout visible for 5000ms' : 'Timeout expired!'}</p>
    </div>
  )
}