Parameters
value: The value to be debounced.delay: The delay in milliseconds before the value is updated.options(optional): Optional configurations for the debouncing behavior.leading(optional): Determines if the debounced function should be invoked on the leading edge of the timeout.trailing(optional): Determines if the debounced function should be invoked on the trailing edge of the timeout.maxWait(optional): The maximum time the debounced function is allowed to be delayed before it's invoked.equalityFn(optional): A custom equality function to compare the current and previous values.
Returns
An array containing the debounced value and the function to update it.
Dependency
This hook is built upon lodash.debounce.
Related hooks
useDebounceCallback:useDebounceValueis built on top ofuseDebounceCallback, it gives more control.
Usage
import { useDebounceValue } from './useDebounceValue'
export default function Component({ defaultValue = 'John' }) {
const [debouncedValue, setValue] = useDebounceValue(defaultValue, 500)
return (
<div>
<p>Debounced value: {debouncedValue}</p>
<input
type="text"
defaultValue={defaultValue}
onChange={event => setValue(event.target.value)}
/>
</div>
)
}
API
function useDebounceValue(initialValue: T | () => T, delay?: number, options?: UseDebounceValueOptions<T>): unknown
Custom hook that returns a debounced version of the provided value, along with a function to update it.
Parameters
| Name | Type | Default value | Description |
|---|---|---|---|
initialValue | `T | () => T` | - |
delay? | number | 500 | The delay in milliseconds before the value is updated. |
options? | UseDebounceValueOptions<T> | - | Optional configurations for the debouncing behavior. |
Returns
An array containing the debounced value, the function to update it, and whether an update is pending.
Type declaration
UseDebounceValueOptions
Hook options.
| Name | Type | Description |
|---|---|---|
equalityFn | (left: T, right: T) => boolean | A function to determine if the value has changed. Defaults to a function that checks if the value is strictly equal to the previous value. |
leading | boolean | Determines whether the function should be invoked on the leading edge of the timeout. |
maxWait | number | The maximum time the specified function is allowed to be delayed before it is invoked. |
trailing | boolean | Determines whether the function should be invoked on the trailing edge of the timeout. |
Hook
import { useCallback, useRef, useState } from 'react'
import type { DebouncedState } from '../useDebounceCallback'
import { useDebounceCallback } from '../useDebounceCallback'
/**
* Hook options.
* @template T - The type of the value.
*/
export type UseDebounceValueOptions<T> = {
/**
* Determines whether the function should be invoked on the leading edge of the timeout.
* @default false
*/
leading?: boolean
/**
* Determines whether the function should be invoked on the trailing edge of the timeout.
* @default false
*/
trailing?: boolean
/**
* The maximum time the specified function is allowed to be delayed before it is invoked.
*/
maxWait?: number
/** A function to determine if the value has changed. Defaults to a function that checks if the value is strictly equal to the previous value. */
equalityFn?: (left: T, right: T) => boolean
}
/**
* Custom hook that returns a debounced version of the provided value, along with a function to update it.
* @template T - The type of the value.
* @param {T | (() => T)} initialValue - The value to be debounced.
* @param {number} [delay=500] - The delay in milliseconds before the value is updated.
* @param {object} [options] - Optional configurations for the debouncing behavior.
* @returns {[T, DebouncedState<(value: T) => void>, boolean]} An array containing the debounced value, the function to update it, and whether an update is pending.
* @public
* @see [Documentation](https://usehooks-ts.com/react-hook/use-debounce-value)
* @example
* ```tsx
* const [debouncedValue, updateDebouncedValue, isPending] = useDebounceValue(inputValue, 500);
* ```
*/
export function useDebounceValue<T>(
initialValue: T | (() => T),
delay = 500,
options?: UseDebounceValueOptions<T>,
): [T, DebouncedState<(value: T) => void>, boolean] {
const eq = options?.equalityFn ?? ((left: T, right: T) => left === right)
const unwrappedInitialValue = initialValue instanceof Function ? initialValue() : initialValue
const [debouncedValue, setDebouncedValue] = useState<T>(unwrappedInitialValue)
const previousValueRef = useRef<T | undefined>(unwrappedInitialValue)
const [isPending, setIsPending] = useState(false)
const internalDebounce = useDebounceCallback(
(value: T) => {
setDebouncedValue(value)
setIsPending(false)
},
delay,
options,
)
const updateDebouncedValue = useCallback(
Object.assign(
(value: T) => {
setIsPending(true)
return internalDebounce(value)
},
{
cancel: () => {
internalDebounce.cancel()
setIsPending(false)
},
flush: () => internalDebounce.flush(),
isPending: () => internalDebounce.isPending(),
},
) as DebouncedState<(value: T) => void>,
[internalDebounce],
)
// Update the debounced value if the initial value changes
if (!eq(previousValueRef.current as T, unwrappedInitialValue)) {
updateDebouncedValue(unwrappedInitialValue)
previousValueRef.current = unwrappedInitialValue
}
return [debouncedValue, updateDebouncedValue, isPending]
}