UNPKG

react-enhanced-debounce-hook

Version:

A tiny, dependency-free React hook library for debouncing values and state. Includes two ergonomic APIs so you can pick the pattern that fits your use-case:

145 lines (105 loc) 3.81 kB
# react-enhanced-debounce-hook A tiny, dependency-free React hook library for debouncing values and state. Includes two ergonomic APIs so you can pick the pattern that fits your use-case: * `useDebounce(value, delay?, options?)` API-compatible with [`use-debounce`](https://github.com/xnimorz/use-debounce) (returns debounced value + controls). * `useDebounceState(initial, delay?)` single-hook UX that returns immediate value, setter, debounced value, and controls (no need for two local states). Perfect for **search inputs, typeaheads, autosave, preventing noisy API calls, and improving UI responsiveness**. --- ## Install ```bash npm install react-enhanced-debounce-hook # or yarn add react-enhanced-debounce-hook ``` simple usage example in CodeSandbox: https://codesandbox.io/p/sandbox/8vxv8j --- ## Usage ### `useDebounceState(initial, delay?)` ```jsx import React, { useEffect } from "react"; import { useDebounceState } from "react-enhanced-debounce-hook"; function SearchBox() { const [value, setValue, debouncedValue] = useDebounceState("", 300); useEffect(() => { if (debouncedValue) { console.log("Trigger API call with:", debouncedValue); // fetch(`/api/search?q=${debouncedValue}`) } }, [debouncedValue]); return ( <div> <input type="text" placeholder="Search..." value={value} onChange={(e) => setValue(e.target.value)} /> <p>Immediate: {value}</p> <p>Debounced (after 300ms): {debouncedValue}</p> </div> ); } ``` --- ### `useDebounce(value, delay?, options?)` ```jsx import React, { useState } from "react"; import { useDebounce } from "react-enhanced-debounce-hook"; export default function DemoUseDebounce() { const [text, setText] = useState("Hello"); // const [debouncedText, controls] = useDebounce(text, 1000); const [debouncedText] = useDebounce(text, 1000); return ( <div style={{ padding: 20, fontFamily: "Arial" }}> <h3>useDebounce demo</h3> <input value={text} onChange={(e) => setText(e.target.value)} style={{ padding: 8, width: 320 }} /> <div style={{ marginTop: 8 }}> <div> Actual value: <b>{text}</b> </div> <div> Debounced value: <b>{debouncedText}</b> </div> </div> {/* <div style={{ marginTop: 8 }}> <button onClick={() => controls.flush()}>Flush (apply now)</button> <button onClick={() => controls.cancel()} style={{ marginLeft: 8 }}> Cancel pending </button> </div> */} </div> ); } ``` --- ## API Reference ### `useDebounce(value, delay?, options?)` * **value**: any value to debounce * **delay**: debounce time in ms (default: `500`) * **options**: * `leading`: trigger immediately on the first call * `trailing`: trigger after the delay (default: `true`) **Returns:** `[debouncedValue, controls]` * `debouncedValue` the debounced version of your value * `controls` `{ cancel, flush }` to cancel or force flush --- ### `useDebounceState(initial, delay?)` * **initial**: initial state value * **delay**: debounce time in ms **Returns:** `[value, setValue, debouncedValue, controls]` * `value` the immediate state (updates instantly) * `setValue` setter function * `debouncedValue` debounced state (updates after delay) * `controls` `{ cancel, flush }` --- ## When to Use Which? * Use **`useDebounce`** if you already manage your own state. * Use **`useDebounceState`** if you want a single hook to handle both **immediate and debounced state** without boilerplate. --- ## License MIT © 2025