The React Hooks Cheat Sheet
The short answer
React ships eleven commonly used built-in hooks: useState, useEffect, useContext, useReducer, useCallback, useMemo, useRef, useLayoutEffect, useId, useTransition and useSyncExternalStore. Everything else — persisting to localStorage, debouncing a value, detecting clicks outside an element, watching a media query — is a custom hook you either write yourself or install. @danixsoft/hooks provides 44 of the most common ones with zero dependencies and full TypeScript types.
Hooks replaced class components in 2019 and have barely changed since. What has changed is the set of problems people solve with them. This page is two references in one: the built-in hooks React gives you, and the custom hooks almost every application ends up needing.
Key takeaway
If you find yourself writing the same useEffect in three components, that is a custom hook trying to get out. The whole point of hooks is that stateful logic becomes portable.
The built-in React hooks
These come with React itself. You never install them, and every custom hook is ultimately built out of them.
The two rules that catch everyone
Hooks must be called at the top level of a component or another hook — never inside a condition, loop, or nested function — and only from React functions. React tracks hooks positionally, so a conditional hook shifts every subsequent hook by one and corrupts your state.The custom hooks every app ends up needing
React deliberately stops at primitives. The gap between useState and a working feature is where custom hooks live. Below is that gap, grouped the way it actually shows up in a codebase.
State that has to outlive a render
Plain useState is gone the moment the component unmounts. Preferences, drafts and dismissals usually need to survive a reload — or at least a route change.
Reading the browser
Viewport size, media queries, scroll position, visibility, network status. Each one is an event listener plus cleanup plus an SSR guard — three chances to get it subtly wrong.
useMediaQuery
Subscribe to a CSS media query from JavaScript.
useWindowSize
Live viewport width and height.
useOnScreen
Boolean that tells you whether an element is visible.
useOnlineState
Track whether the browser is online.
useWindowScroll
Current window scroll offset, plus a scrollTo helper.
useScreen
The window.screen object as reactive state.
Timing and rate limiting
A search box that fires a request on every keystroke is the single most common performance bug in React applications. Debouncing it is one line.
query so typing feels instant, while the request uses debouncedQuery. Swapping them makes the field feel laggy.Interaction and gestures
useClickOutside
Run a handler when a click lands outside an element.
useHover
Ref plus a boolean for pointer-over state.
useMouse
Pointer position, page-wide or relative to an element.
useSwipe
Detect swipe direction and distance on touch devices.
useCopyToClipboard
Copy text to the clipboard and read back what you copied.
Lifecycle escape hatches
These exist because useEffect alone cannot express "only on updates", "only on unmount", or "always the latest closure" without boilerplate that is easy to get wrong.
The five mistakes that account for most hook bugs
- 1
Stale closures in intervals and event handlers
A callback registered once captures the state from that render forever.
useIntervalanduseEventboth solve this by keeping the callback in a ref and always invoking the latest version. - 2
Missing cleanup
Every subscription, timer and listener you create in an effect must be returned as a cleanup function. Forgetting this leaks memory and, in React Strict Mode, doubles your side effects in development.
- 3
Objects and arrays in dependency arrays
A fresh object literal is a new identity on every render, so the effect runs every time. Depend on primitive fields, or memoise the object with
useMemo. - 4
Reaching for useMemo too early
Memoisation is not free — it costs a comparison and extra memory on every render. Measure before you memoise anything cheaper than a few milliseconds.
- 5
Touching window during server rendering
Any hook that reads
window,document,localStorageornavigatormust guard for the server, or your Next.js build will crash and your hydration will mismatch.
Install the whole set
Every hook linked on this page is a named export from one tree-shakeable package.
How many hooks does React have built in?
React 19 exposes around a dozen hooks in common use: useState, useEffect, useContext, useReducer, useCallback, useMemo, useRef, useImperativeHandle, useLayoutEffect, useDebugValue, useId, useDeferredValue, useTransition, useSyncExternalStore and useActionState. Most applications use five or six of them regularly.
Should I write my own hooks or install a library?
Write your own for logic specific to your product — that is the whole point of custom hooks. Install a library for the generic, well-understood problems (debouncing, localStorage, media queries) where a well-tested implementation already exists and the edge cases are known.
Do custom hooks hurt performance?
No. A custom hook is a plain function call; it adds no component to the tree and no extra render. Performance depends on what the hook does internally, not on the fact that it is a hook.
Can a custom hook call another custom hook?
Yes, and that is normal. Hooks compose freely as long as every call happens at the top level of the function. Several hooks in this library are built on top of others in it.
Keep reading
Writing custom hooks that survive production
Naming, return shapes, dependency arrays, cleanup, testing and TypeScript patterns for custom React hooks that other people have to maintain.
SSR-safe hooks in Next.js
Why "window is not defined" and hydration mismatches happen, and the four patterns that fix them for good in Next.js, Remix and any server-rendered React app.