How do you write a custom hook and what makes it useful?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
A custom hook is a function named use* that composes built-in hooks and returns values/functions to callers. It extracts reusable stateful logic while keeping state isolated per component instance.
Detailed explanation
Custom hooks solve logic duplication, not rendering duplication: each component calling useToggle() gets its own independent state because hooks are per-instance, unlike extracting a shared component. Conventions matter — names must start with 'use' so lint rules apply and React's hook ordering assumptions hold: call hooks unconditionally at the top level of the hook, never inside loops or conditions. Typical patterns: useFetch wrapping loading/error/data handling, useLocalStorage syncing state with storage events, useDebounce returning a debounced value, useMediaQuery for responsive behavior. A good custom hook returns a small explicit API (tuple or object), documents side effects, cleans up after itself, and stays presentation-free. Testing them is straightforward with @testing-library/react-hooks style renderHook utilities.
Official docs:React docs: Reusing Logic with Custom Hooks
Example
function useLocalStorage<T>(key: string, initial: T) {
const [value, setValue] = useState<T>(() => {
try {
const raw = localStorage.getItem(key);
return raw ? (JSON.parse(raw) as T) : initial;
} catch { return initial; }
});
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
return [value, setValue] as const;
}Interview tip
Emphasize 'per-component isolated state' as the differentiator vs plain utility functions, then demo a small real hook like useLocalStorage end-to-end.
Common mistakes
- Conditionally calling hooks inside custom hooks.
- Building hooks so tightly coupled to one component that reuse is impossible.