Home > Enterprise >  Custom React Hook for setting a ref with delay
Custom React Hook for setting a ref with delay

Time:10-19

Let's say I have some code like this:

const X = useRef<boolean(false)
const setX = (value: boolean) => {
    if (value) {
        window.setTimeout(() => {
            X.current = false;
    }, 1000);
    X.current = value
}

So that when I call setX(true), X is only true for one second.

I have a bunch of these repeated in code, and would like to make a hook out of it. Something like:

const [X, setX] = useSetWithDelay(false, 1000)
const [Y, setY] = useSetWithDelay(false, 1000)
...

How can I do that?

CodePudding user response:

Like so:

const useSetWithDelay = (initialValue: boolean, timeout: number) => {
  const ref = useRef<boolean>(initialValue);
  const setValue = (value: boolean) => {
    window.setTimeout(() => ref.current = false, timeout);
    ref.current = value
  }
  return [ref.current, setValue];
};

CodePudding user response:

Create a custom hook using generics that infer the type from the base value:

const useTempSet = <T>(base: T, delay = 1000) => {
  const timeout = useRef<ReturnType<typeof setTimeout>>(null)
  const ref = useRef<T>(base)

  const set = useCallback((value: T) => {
    if(timeout.current) clearTimeout(timeout.current) // clear previous timeout
  
    timeout.current = setTimeout(() => {
      ref.current = base
    }, delay)

    ref.current = value
  }, [base, delay])

  return [ref, set]
}

Note: using if (value) { to set the timeout would fail if the value is falsy, for example calling the set function with false, null or 0.

  • Related