react-use: a hooks collection whose pre-push hook deletes the build and runs the suite again
GitHub describes it as React Hooks , 👍. The repository metadata lists TypeScript as its primary language. The metadata lists the Unlicense license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- react-use is a large set of React hooks grouped by what they touch rather than what they do, published under the Unlicense. Its build details are more informative than its feature list: two compiled outputs, a separate jest config for server rendering, and a pre-push hook that cleans, rebuilds and retests before anything leaves your machine.
- Who is it for?
- react-use fits a React codebase that keeps reaching for the same browser event wiring and wants it already written, tested against server rendering, and licensed permissively enough to vendor.
- Can I use it commercially?
- Yes. Unlicense is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 112 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The pre-push hook deletes the build and runs the suite from scratch
The husky configuration in package.json has two hooks. Pre-commit runs lint-staged. Pre-push runs `yarn lint && yarn clean && yarn build && yarn test`, and `clean` is `rimraf lib storybook-static esm`.
So every push lints the source, deletes both compiled outputs and the Storybook build directory, recompiles them with two separate TypeScript invocations, and then runs jest. Nothing incremental survives a push.
That is an unusual amount of work to do on every push, and it is deliberate in a way a reader can infer. The published package contains only `lib/` and `esm/`, both of which the clean step removes, so a push that skipped the rebuild could ship a stale artefact, and a push that skipped the clean could ship a file no longer produced by the source. The consequence for a contributor is that a push is slow and that a type error which `tsc` would catch in production shows up as a failed push rather than as a bug report.
Two compiled outputs, and sideEffects false tells bundlers to drop them
The manifest is small and deliberate. `main` is `lib/index.js`, `module` is `esm/index.js`, and both `types` and `typings` point at `lib/index.d.ts`. The `files` array publishes exactly two directories, `lib/` and `esm/`, and `sideEffects` is `false`.
The two outputs come from two commands. `build:cjs` is a plain `tsc`, and `build:es` is `tsc -m esNext --outDir esm`, so the ESM build is the same source compiled a second time with a different module target. One source tree, two module systems, one declaration file, taken from the CommonJS output.
`sideEffects: false` is the load-bearing field. It tells a bundler that importing a hook has no side effects, so unused imports can be dropped entirely, which is the difference between a hooks collection costing you one kilobyte and costing you the whole package. The consequence is a constraint on the code as well as on the bundler: any hook with a registration side effect at import time would be silently removed by a tree shaking bundler, so every hook in the collection has to keep its work inside the component lifecycle.
Three jest configs, and one of them exists to catch window access
There are three configuration files at the top level: `jest.config.base.ts`, `jest.config.ts` and `jest.config.node.ts`. The scripts distinguish them. The ordinary run is `jest --maxWorkers 2` with the default config, and the server rendering run is `jest --maxWorkers 2 --config ./jest.config.node.ts`.
The two workers are capped rather than left to the machine, which keeps a large suite from starving itself on a laptop and keeps timing comparable between machines.
The node config is the interesting one for a hooks library. A hook that reads `window`, `document` or `localStorage` at module scope will pass in a browser like test environment and fail the moment somebody renders the same component on a server, which is exactly the bug a React library is most likely to ship. Running the suite under a node config catches it before a consumer does. The consequence is that a hook reading a browser global has to guard the read, and the cost of that guard is visible in the code rather than in a support ticket.
The dependency list is the inventory of what the hooks refuse to reimplement
The runtime dependencies are few and each one answers a question a hook would otherwise have to solve. `copy-to-clipboard` handles the clipboard, `js-cookie` handles cookies, `@xobotyi/scrollbar-width` measures the browser's native scrollbar, `resize-observer-polyfill` provides the observer where it is missing, `nano-css` handles the dynamic CSS hook, `react-universal-interface` handles the platform differences, and `fast-deep-equal` with `fast-shallow-equal` supply the comparison functions the equality hooks need.
That is the whole list, and reading it tells you what the collection does not implement. It is not an animation library, a router or a data layer, and the animation category is a handful of hooks built on `requestAnimationFrame` and `setInterval` rather than a physics engine, with `useSpring` interpolating a number over time according to spring dynamics.
The consequence for a reader weighing bundle size is that the number is per dependency, not per package. A project that uses one clipboard hook still resolves the whole dependency graph at install time, and while `sideEffects: false` keeps unused code out of the bundle, the install cost and the update surface are paid in full.
The pairs in the list tell you which variant re-renders on every event
The README groups the hooks under Sensors, UI and Animations, each entry a link to a Markdown doc in `docs/` with a one line description and a demo link. What the grouping does not say is the convention the names follow, and reading the pairs makes it visible.
`useHover` and `useHoverDirty`. `useMouse` and `useMouseHovered`. `useMeasure` and `useSize`. `useKey`, `useKeyPress`, `useKeyboardJs` and `useKeyPressEvent`. `useDrop` and `useDropArea`. `useInterval` and `useHarmonicIntervalFn`. `useLocation` and `useSearchParam`.
Where a pair exists, one member is the callback style that runs your function and the other holds state, and the suffix marks the one that forces a re-render on every event rather than calling back. `useHoverDirty` and `useMouseHovered` are the two members that carry that mark in the Sensors list. The consequence is practical: picking the wrong member of a pair is not a subtle performance difference, it is a component that re-renders on every pointer move, and the fix is to read the doc for that hook rather than the list entry.
17.6.1 is a patch on a line that sat for eighteen months
The release list reads v17.6.1 published 2026-06-10, v17.6.0 published 2024-12-09, and v17.5.1 published 2024-07-20. Versioning is handled by `semantic-release`, so the numbers are derived from commit messages rather than typed by hand, and the patch bump on a version that had not moved in a year and a half reflects whatever the convention decided was a fix.
The last push to the default branch, master, is 2026-06-10, the same day as that release. The repository is not archived, but the branch has been still since the version went out, which is a different statement from being actively worked on.
The consequence is about what you can expect. A patch on a dormant line means the collection is stable in the sense that its API is not moving, and it means a bug you hit is not going to be fixed by a release next month. Anyone depending on it should read `CHANGELOG.md` for what actually changed in 17.6.1 rather than inferring from the number, and `CONTRIBUTING.md` is the file to read before assuming a fix would be accepted quickly.
Docs are Markdown per hook and Storybook stories published to gh-pages
Documentation is two systems. Every hook has a Markdown file under `docs/`, which is what the README links to, and the demos come from Storybook: `start-storybook -p 6008` for local work, `build-storybook` to produce it, and `storybook:upload` to push the output with `gh-pages -d storybook-static --git "$(which git)"`. The `stories/` directory and the `.storybook/` config hold the stories, and the `storybook:clean` script removes the output the same way `clean` removes the build.
The demo links in the README point at two different hosts. Several go to codesandbox.io, and the rest go to story URLs under streamich.github.io/react-use.
So a link in the README can break independently of the package. A CodeSandbox sandbox is someone else's hosted project and can disappear, and a Storybook story URL breaks if a story is renamed or if the docs site is rebuilt with different paths, while the hook itself keeps working in your node_modules. The consequence for a reader is to treat the demo link as a convenience and the `docs/` Markdown file as the reference, and for a contributor the `docs/` file is the one that has to be updated when a hook's signature changes.
Editorial conclusion
react-use fits a React codebase that keeps reaching for the same browser event wiring and wants it already written, tested against server rendering, and licensed permissively enough to vendor. It is a poor fit if your bundle budget is measured in kilobytes per hook rather than per package, since each hook that wraps a browser API also brings a dependency, and a poor fit if you need a stream of new hooks, since the newest release is a patch from 2026-06-10 sitting on a line that had been quiet since December 2024. Before adopting it, read the doc for the specific hook rather than the list entry, and check whether the paired variant, the Dirty or the rerendering one, is the one you actually want.
Frequently asked questions
How do I install react-use?
The install line in the README is `npm i react-use`. The package is named react-use, publishes only `lib/` and `esm/`, and is released under the Unlicense, so there is no attribution requirement on code taken from it.
is react use typescript
It is written in TypeScript. The repository is a TypeScript project with a tsconfig.json, the lint script targets `{src,tests,stories}/**/*.{ts,tsx}`, `lint:types` runs `tsc --noEmit`, and the published declaration file is `lib/index.d.ts`, referenced by both `types` and `typings`.
How do I use a react-use hook?
Import the hook by name and call it in a component, the same way a built-in hook is used. The README groups them as Sensors, UI and Animations, and each entry links to a Markdown file under docs/ plus a demo, with pairs such as useHover and useHoverDirty for the callback and re-rendering variants.
What are the react use alternatives?
The repository names no alternatives. What it declares is its own scope: a collection of essential React Hooks, described as a port of libreact, with runtime dependencies limited to small utilities such as copy-to-clipboard, js-cookie, nano-css, a scrollbar width measurement package and a resize observer polyfill.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/streamich-react-use)