Frontend
easy
mid
What hooks would you extract for reusability
Extract hooks where logic is duplicated, stateful, or involves effects/subscriptions: data fetching, form handling, debounced values, media queries, local storage sync, intersection observers, pagination, and event listeners. Extract for reuse or clarity — not prematurely.
6 min read·~10 min to think through
Custom hooks are how you share stateful logic without sharing markup. Extract when logic is repeated, involves an effect/subscription, or is complex enough that naming it clarifies the component.
Strong candidates to extract
Data & async
useFetch/useQuery-style data loading (or just use React Query).usePagination,useInfiniteScroll.useAsync— wraps a promise with loading/error/data state.
Input & timing
useDebounce/useThrottle— debounced value or callback.useForm/useFormField— value, validation, touched/dirty state.
Browser APIs & subscriptions
useMediaQuery— responsive logic in JS.useLocalStorage/useSessionStorage— state synced to storage, with thestorageevent.useIntersectionObserver— lazy loading, infinite scroll, visibility.useEventListener— add/remove listeners with correct cleanup.useOnlineStatus,useWindowSize,useScrollPosition.
UI behavior
useToggle,useDisclosure(open/close + handlers).useClickOutside— dismiss popovers/menus.usePrevious— previous value of a prop/state.useHover,useFocusWithin.
App-domain hooks
useAuth,useCart,useFeatureFlag— domain logic behind a clean API.
Principles for good hooks
- Single responsibility — a hook does one thing; name says what.
- Stable return shape — return memoized values/callbacks so consumers don't re-render needlessly.
- Handle cleanup — every subscription/listener/timer cleaned up in the effect return.
- Composable — small hooks compose into bigger ones (
useInfiniteScrollbuilt onuseIntersectionObserver). - Don't return JSX — that's a component, not a hook.
When not to extract
- Used once and trivial — inline is clearer.
- Extraction would just relocate complexity without reducing it.
- The "hook" is really a component (it renders).
Don't pre-build a hooks library; extract the second time you copy-paste, or the moment a component's logic obscures its rendering.
Follow-up questions
- •What makes a custom hook well-designed vs a leaky abstraction?
- •Why should hooks return memoized/stable references?
- •How do you compose smaller hooks into larger ones?
- •When is extracting a hook premature?
Common mistakes
- •Extracting hooks prematurely for single-use trivial logic.
- •Hooks that return new object/function references each render, causing re-renders.
- •Forgetting cleanup for listeners/subscriptions/timers.
- •Building a 'hook' that really should be a component.
Performance considerations
- •Hooks should memoize returned values and callbacks (useMemo/useCallback) so consumers stay stable. A poorly designed hook can spread re-renders. Each hook call is independent state — don't expect cross-component sharing without a store/context.
Edge cases
- •Hooks with dependencies that change identity every render.
- •Hooks used conditionally (violates rules of hooks).
- •SSR — hooks touching window/localStorage need guards.
- •Hooks sharing state vs each call getting its own instance (they get their own).
Real-world examples
- •useDebounce powering a search input across the whole app.
- •useIntersectionObserver shared by lazy images, infinite scroll, and analytics impression tracking.
Senior engineer discussion
Seniors extract along the 'repeated, stateful, or effectful' axis and emphasize hook API quality — single responsibility, stable references, cleanup, composability. They distinguish generic utility hooks from domain hooks (useCart, useAuth) and warn against a speculative hooks library; extraction follows real duplication or clarity needs.
Related questions
Frontend
Medium
6 min
Frontend
Medium
6 min