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
.