enso/app/dashboard/src/hooks/debounceStateHooks.ts
2024-07-26 17:47:59 +10:00

44 lines
1.2 KiB
TypeScript

/**
* @file
*
* This file contains the `useDebounceState` hook,
* which is a custom hook that returns a stateful value and a function to update it that will debounce updates.
*/
import * as React from 'react'
import * as debouncedCallback from './debounceCallbackHooks'
import * as eventCallbackHooks from './eventCallbackHooks'
/**
* A hook that returns a stateful value, and a function to update it that will debounce updates.
*/
export function useDebounceState<S>(
initialState: S | (() => S),
delay: number,
maxWait = 0,
): [S, React.Dispatch<React.SetStateAction<S>>] {
const [state, setState] = React.useState(initialState)
const currentValueRef = React.useRef(state)
const [, startTransition] = React.useTransition()
const debouncedSetState = debouncedCallback.useDebouncedCallback<
React.Dispatch<React.SetStateAction<S>>
>(
(value) => {
startTransition(() => {
setState(value)
})
},
[],
delay,
maxWait,
)
const setValue = eventCallbackHooks.useEventCallback((next: S | ((currentValue: S) => S)) => {
currentValueRef.current = next instanceof Function ? next(currentValueRef.current) : next
debouncedSetState(currentValueRef.current)
})
return [state, setValue]
}