usethishook
v1.3.0
Published
Promise-based confirm/prompt dialogs and 53 tree-shakeable React hooks. Zero runtime deps, TypeScript, SSR-safe, live playground.
Maintainers
Readme
useThisHook
Promise dialogs, 53 typed hooks, zero runtime deps, live playground.
Await confirm() / prompt() in a click handler. Import only the hooks you need — debounce,
storage, forms, browser APIs. TypeScript. SSR-safe. React 18+.
npm i usethishookPlayground · Compare vs usehooks-ts · MCP for Cursor · npm · Wiki · Changelog
What’s new in 1.3.0
- Async:
useAsyncState,useOptimisticAction,useRetry,useAsyncQueue,usePolling - Browser / PWA:
useOnlineQueue,useStorageQuota,useInstallPrompt,useCrossTabState - Debug:
useRenderTracker,useWhyDidYouUpdate(logging off in production by default) - Interaction:
useKeyboardShortcut,useLongPress - AI tools:
usethishook-mcpcatalogs all 53 hooks for Cursor and Claude Desktop
See CHANGELOG.md, RELEASE_NOTES.md, and the playground.
New to React hooks?
A hook is a small function whose name starts with use (like useState).
You call it inside a component to get state or behavior — without writing that plumbing yourself.
With useThisHook you:
- Install the package
- Import one hook
- Use it like any other React hook
No UI kit. No config file. Import only what you need.
60-second demo: await a confirm dialog
Ask the user before deleting — right in your click handler:
import { useConfirm } from 'usethishook';
export const DeleteButton = () => {
const { confirm, render } = useConfirm();
return (
<>
<button
type="button"
onClick={async () => {
if (await confirm({ title: 'Delete this row?', danger: true })) {
// user said yes — delete here
}
}}
>
Delete
</button>
{render()}
</>
);
};useConfirm live demo · StackBlitz · also try usePrompt · useOverlay · useStepFlow · useFingerprint · useAmountInput
Everyday hooks (same idea)
import { useBoolean, useDebounce, useLocalStorage } from 'usethishook';
export const SearchBox = () => {
const { value: isOpen, toggle } = useBoolean(false);
const [query, setQuery] = useLocalStorage('search', '');
const debouncedQuery = useDebounce(query, 300);
return (
<div>
<button type="button" onClick={toggle}>
{isOpen ? 'Hide' : 'Show'} search
</button>
{isOpen && <input value={query} onChange={(event) => setQuery(event.target.value)} />}
<p>Searching for: {debouncedQuery}</p>
</div>
);
};Why teams pick it
| You want… | You get… |
| ---------------------------- | ------------------------------------------------------ |
| Less boilerplate | Toggles, timers, forms, lists, URL state — ready |
| Dialogs without a UI library | await confirm() / prompt() / custom overlays |
| A small install | Zero runtime deps (React is a peer only) |
| Safe imports | Tree-shakeable ESM + CJS with bundled TypeScript types |
| Works with Next / Vite / SSR | Browser hooks use safe defaults until the client runs |
Works with React 18+, Node 20+, Vite, Next.js, CRA, and Module Federation.
How this differs from usehooks-ts and react-use: comparison (zero runtime deps, promise dialogs, playground).
Using Cursor or Claude? Point MCP at usethishook-mcp so the agent can search hook docs instead of guessing APIs.
All hooks
Every hook has a live preview + API on the playground.
State
| Hook | What it does |
| ------------------------------------------------------------------------------ | ----------------------------------------- |
| useBoolean | On/off state with toggle helpers |
| useDisclosure | Open / close / toggle for menus & dialogs |
| useDebounce | Wait until a value stops changing |
| useThrottle | Limit how often a value updates |
| useInterval | Run on an interval (null pauses) |
| useCopyToClipboard | Copy text + remember last copy |
| useLocalStorage | State that survives refresh |
| useSessionStorage | State that survives refresh (tab-scoped) |
| useCrossTabState | JSON state synced across tabs |
Browser
| Hook | What it does |
| ------------------------------------------------------------------------------------ | ------------------------------------------- |
| useOnlineStatus | Online / offline |
| useOnlineQueue | Queue while offline, flush when online |
| useStorageQuota | Storage usage and quota |
| useInstallPrompt | PWA install prompt |
| useFingerprint | Client-side visitor id from browser signals |
| useMediaQuery | Match a CSS media query |
| useWindowSize | Viewport width & height |
| useOnClickOutside | Detect clicks outside an element |
| useEventListener | Stable DOM / window listener |
| useTimeout | One-shot timer (null pauses) |
| useKeyPress | Key held down (skips text fields) |
| useKeyboardShortcut | Key combo on window, cleaned up on unmount |
| useLongPress | Mouse and touch press-and-hold |
| useScrollLock | Lock / unlock document body scroll |
| useDocumentVisibility | Tab visible or hidden |
| useIdle | Idle after no user activity |
| useOverlay | Custom overlay as a Promise |
| useStepFlow | Multi-step wizard that resolves when done |
| useAsyncSelect | Native file picker as a Promise |
App
| Hook | What it does |
| ---------------------------------------------------------------------------------- | ------------------------------------------ |
| useStableCallback | Stable function, always latest body |
| useUpdateEffect | useEffect that skips the first mount |
| useResetState | Reset state when a key changes |
| useAsyncAction | Pending / error / data for one async call |
| useAsyncState | Idle / loading / success / error + abort |
| useOptimisticAction | Optimistic update with rollback |
| useRetry | Retry with backoff and cancel |
| useAsyncQueue | Concurrent async task queue |
| usePolling | Polling that pauses when the tab is hidden |
| useDebouncedCallback | Debounce a function |
| useThrottledCallback | Throttle a function |
| useFields | Small form object, optional schema |
| useAmountInput | Locale-aware money / amount input |
| useList | Insert / update / remove / reorder by id |
| useSelection | Single or multi select by id |
| useSearchState | URL search params as React state |
| useConfirm | Await a yes/no dialog |
| usePrompt | Await a string from a dialog |
| useControllableState | Controlled + uncontrolled in one API |
| useUnsavedChanges | Warn before leaving with dirty data |
| useElementSize | Element size via ResizeObserver |
| useInView | Visibility via IntersectionObserver |
| usePagination | Page, offset, next / prev |
| useRenderTracker | Render counts (dev logging) |
| useWhyDidYouUpdate | Which values changed (dev logging) |
Contributing
We welcome PRs — new hooks, clearer demos, docs, and bug fixes all help.
- Read CONTRIBUTING.md (and the Code of Conduct)
- Pick an issue or open a Discussion with an idea
- Run the local playground while you work:
npm install && npm run playground
npm install
npm test
npm run playground # usually http://localhost:5173Good first wins: tighten a demo, fix a typo, add a test, or document a gotcha you hit as a beginner.
Questions? Discussions · Bugs? Issues
Sponsors
useThisHook is MIT and free forever. If it saves you time, a sponsor helps cover hosting, tooling, and continued hook work.
Stars, shares, and “used it in production” notes also go a long way — thank you.
MCP (AI coding tools)
{
"mcpServers": {
"usethishook": {
"command": "npx",
"args": ["-y", "usethishook-mcp"]
}
}
}Tools: list_hooks, search_hooks, get_hook, recommend_hook. Full setup: mcp/README.md · playground MCP page.
More
- Support — where to ask questions
- Security — report vulnerabilities privately
- Roadmap — what’s next
- Migration · Release
- Compare — vs usehooks-ts and react-use
