Custom Hooks in React
Extract reusable stateful logic
A technique to reuse stateful logic across components without repeating code. Part of advanced React: the built-in hooks arenât the limit â you write your own.
What it is
- A function whose name starts with
useand that calls other hooks inside. - It extracts logic (state, effect, context) for reuse. Unlike a component, it returns no JSX â it returns data and/or functions.
- â ïž It doesnât share state: each component using the hook gets its own isolated state instance.
The rules of hooks (they apply to yours too)
- Only call hooks at the top level of a component/hook â never inside
if, a loop, or a callback. - Only call them inside React components or other hooks.
- â ïž
eslint-plugin-react-hooksenforces these rules and the dependency array.
The âcallback in a refâ pattern (used across this collection)
The hooks below keep the callback in a useRef and update it in a separate effect. Why?
So the effect that registers the listener/timer runs once (stable deps) without
capturing a stale version of the callback.
const savedCallback = useRef(callback);
// Always keeps the latest reference, without re-attaching the listener.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Inside, call savedCallback.current() instead of callback.
Without it, either the effect recreates the listener every render, or it fires the old closure.
When to build a custom hook
- The same state/effect logic shows up in 2+ components.
- A component grew and its non-visual logic can move into a named hook.
- â ïž Donât make a hook just to group code: if it uses no state/effect/context, itâs a plain pure function.
The collection
- use-listener â listen to
windowevents with debounce. - use-interval â run a function on an interval, declaratively.
- use-debounce â delay a reactive value (e.g. search-as-you-type).
- use-throttle â cap how often a value updates.
- use-on-click-outside â detect a click outside an element.
- use-local-storage â state persisted in
localStorage. - use-media-query â react to breakpoints and
prefers-color-scheme.
Related: advanced React · React performance.