# use-debounce's manifest is a full minor ahead of every published tag, and its README examples are built on a test library it no longer depends on

> use-debounce is a MIT-licensed React library exporting three hooks, under one kilobyte, compatible with the lodash implementation style. Its manifest declares a version no release matches, its title names a throttle hook the visible documentation never covers, the rationale for value debouncing is attributed to a single archived post, and the size claim is enforced by a build budget rather than asserted.

**xnimorz/use-debounce** — A debounce hook for react

- Repository: https://github.com/xnimorz/use-debounce
- Stars: 3,381 · Forks: 119
- Language: TypeScript
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/xnimorz-use-debounce

## The manifest is a full minor ahead of every published tag

Three releases are visible, and the version in the manifest matches none of them.

```
"version": "10.1.1",
```

The newest tag is ten point zero point six. Before that, ten point zero point five, and before that ten point zero point four, whose tag name is written with a leading letter that the other two do not have.

So there are two separate inconsistencies. The manifest is a minor version ahead of everything published, and the tags disagree with each other about whether they carry a prefix.

That gap has an innocent explanation. The build script deletes the distribution directory and rebuilds, the test script runs before the build, and the publish hook runs the build, so a working checkout of the default branch will have a version that no registry copy has ever carried.

Which is exactly the problem. A developer on the branch and a developer on the registry are running different code under the same name, and there is no tag that marks where the split happened. The repository is not archived and the last push to the default branch is dated 2026-09-11.

## Three hooks cover values, callbacks and throttling

The README documents `useDebounce` for values, `useDebouncedCallback` for callbacks and `useThrottledCallback` for throttling. It includes examples for each and describes options such as leading and trailing calls; `maxWait` applies to the debounce hooks, not the throttled callback.

## The design rationale for value debouncing is one post, with an archive link

The value-debouncing section opens by attributing its design to a specific person, and then does something unusual.

It cites a social media post by a well-known author of the React documentation, and immediately beneath the citation it provides a link to an archived copy of that post at a web archive address.

Almost nobody does that. Normally a README links a post and hopes it stays up. An archived link means the author expected the original to disappear and wanted the reasoning to survive.

That tells you two things about this project. The design of the value hook is not arbitrary; it is a specific proposal by a specific person, adopted deliberately. And the maintainer cares about that proposal remaining citable years later, in a project whose newest release predates its own manifest.

The section then does something the citation does not: it explains the comparison rule. The hook compares the previous and next value shallowly, which means setting a new object literal every render restarts the timer every render. For deep comparison it points at a specific comment on a specific issue number, and suggests the callback hook instead.

That is a real limitation with a real workaround, and it is one line long.

## The example test is written against a test library the project dropped

The section explaining what a debounced callback returns includes a test rather than a description alone, and the test is a real one.

It mounts a component that holds a debounced callback, calls the cached callback, and asserts three things: that the underlying callback has not been called, that the result is undefined, and that after running the timers the callback has been called exactly once.

That is a well-constructed test for the hazard the section is warning about. Calling a debounced function before the timer fires returns the previous invocation's result, and before any invocation there is nothing to return.

Now look at how it mounts the component. It calls a mount function from Enzyme, the older React test library. The project's development dependencies list the modern testing library instead, and Enzyme is not among them.

So the only executable specification of this behaviour in the README cannot run in this project as configured. Anyone copying it gets a module that is not installed.

The block also stops mid-statement, on the line that would have asserted the subsequent result, so even the intent of the final assertion is cut off.

## Use the upstream examples as a starting point

The README includes examples for value debouncing, callbacks, cancellation, flushing and throttling. Adapt them to your React version and test timer behavior in your own component, including cleanup when a component unmounts.

## The one kilobyte claim is a build budget, not a promise

The feature bullets claim a small size, and unlike most claims in most READMEs, this one is checked.

The manifest configures a size-limit preset for small libraries as a development dependency, and there are two scripts wired to it. One runs the build and then the size check, which makes it usable on demand. The other, the build script, runs the tests, then the build, then the size check, in that order.

So a build that grows past the budget fails. The size is a constraint on the pipeline rather than a number a maintainer typed once.

That also shapes what the library can do. The published files list contains a single directory, the build output, so no source, no test and no configuration ships. The manifest declares no side effects, which is what lets a bundler drop the hooks a component does not import.

The peer dependency list has one entry, the React runtime at any version, and there is no runtime dependency list at all. So the size figure covers a library with nothing inside it except three hooks and their timers.

## The lint command covers one directory level and one file extension

The test script runs the test runner and then a linter, and the linter's argument is a glob.

The glob covers source files with one extension, inside the source directory, with a wildcard for the path segment.

Two things are narrow about it. The wildcard in that position matches a single level in the glob semantics most tools implement, so a file nested two directories deep inside the source tree is not matched. And the pattern names one extension, so the two configuration files at the root and the test directory are outside it.

So the test script is not a whole-repository check. It is a unit test run plus a lint of one directory at one depth.

This is a small project, and small projects often have exactly this arrangement by accident rather than by decision. The presence of a separate prettier configuration and a separate editor configuration at the root suggests formatting was wanted everywhere, which makes the narrow lint glob look more like an oversight than a policy.

## The peer dependency accepts any React and the type definitions pin one major

The peer dependency is the runtime at any version, with no upper or lower bound.

The development dependencies, which are what the type definitions are built against, pin the React types to a version eighteen release and the React DOM types to a matching eighteen release.

So the package will install happily next to a React version two majors newer, and then the types it was compiled against describe an API that may no longer match the one at runtime. There is no build step at install time that would catch that, because there is nothing to build.

This is the standard trade in a hook library: the peer range stays wide so the package never blocks an install, and the mismatch surfaces at compile time in the consumer. The interesting detail is that the widest possible range and a pinned set of types are declared in the same file, ninety lines apart, with nothing reconciling them.

Given the manifest is a full minor ahead of every published tag, it is worth checking whether the type definitions in the version you install correspond to the React version you are on.

## Conclusion

Use use-debounce if you already know the lodash debounce shape and want the same API as a React hook with cancel, a pending check and a flush you can call from an unmount cleanup. It has no runtime dependencies, ships only its build output, and treats its size as a build constraint rather than a claim, which is the strongest signal in a small library. Three things to check before you upgrade. Which version you are actually on, because the manifest sits a full minor ahead of the newest published tag and the tags themselves are inconsistent about whether they carry a version prefix. Whether your React major is covered, since the peer dependency accepts any version while the type definitions are pinned to one. And what the documentation will not tell you, since the throttle hook named in the title has no visible section and several of the six code examples stop mid-statement, so the playground links and the changelog carry the detail the file does not.

## FAQ

### what is use debounce

It is a MIT-licensed React library for debouncing, exporting a hook for values, a hook for debounced callbacks and a hook for throttled callbacks. The README claims a size under one kilobyte, compatibility with the underscore and lodash implementation so the API is the same shape everywhere, and that it is server-rendering friendly. It has no runtime dependencies and publishes only its build output.

### npm i use debounce

The install lines the README gives are yarn add use-debounce, or npm i use-debounce --save. Downloading the sources instead is possible but the README does not recommend it, since you would lose dependency management. The published package contains only the build output directory, so nothing else needs copying.

### What does use-debounce return, and why might I get undefined?

Both hooks return a small control object: a cancel function that stops a pending cycle, a pending check that tells you whether a request is waiting, and a flush that runs a pending call immediately. Separately, calling the debounced function returns the result of the previous invocation, so before anything has run you get undefined, and the README tells you to check for that in your code.

### How does useDebounce decide that a value changed?

It compares the previous and next value with a shallow equality check. That means a new object literal, even with identical contents, restarts the timer every time it is set. The README links a specific comment on a specific issue for the deep-comparison case and suggests the debounced callback hook there instead.

### What are maxWait, cancel and flush for in use-debounce?

The maximum-wait option works with both the value hook and the callback hook and caps how long the function may be delayed before being invoked. Cancel stops a pending cycle. Flush runs a pending call straight away, which the README recommends for the case where the user takes an action that will unmount the component but you still need the callback to run, by calling flush from an effect cleanup.

### How is use-debounce related to lodash debounce?

The README claims compatibility with the underscore and lodash implementation, on the grounds that you learn the API once and can use it everywhere. It does not depend on either library: the manifest has no runtime dependency list at all, only a peer dependency on React. The claim is about API shape rather than about shared code.

## Sources

- [Issues](https://github.com/xnimorz/use-debounce/issues)
- [License: MIT](https://github.com/xnimorz/use-debounce/blob/master/LICENSE)
- [README](https://github.com/xnimorz/use-debounce/blob/master/README.md)
- [Releases](https://github.com/xnimorz/use-debounce/releases)
- [xnimorz/use-debounce on GitHub](https://github.com/xnimorz/use-debounce)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/xnimorz-use-debounce
