HuntExams Academy logo
ReactIntermediate#hooks

How do you create a custom hook?

Answer

Write a function whose name starts with 'use' and which calls other hooks, then return whatever the caller needs. It shares stateful logic, not state — each caller gets its own instance.

Example

function useToggle(initial = false) {
  const [on, setOn] = useState(initial);
  return [on, () => setOn(o => !o)];
}
const [open, toggle] = useToggle();

Detailed explanation

A custom hook is a JavaScript function that extracts reusable React logic involving hooks. Its name must start with `use` followed by a capital letter, such as `useToggle`, so React tooling can recognise it as a hook and enforce the Rules of Hooks. It can accept arguments and return whatever its callers need: a value, an array, an object, or callback functions. Custom hooks are useful when multiple components need the same behaviour, such as toggling a panel, tracking network status, or synchronising with an external system, without duplicating the implementation.

For a toggle, import `useState` from React and write: `function useToggle(initial = false) { const [on, setOn] = useState(initial); return [on, () => setOn(o => !o)]; }`. A component uses it with `const [open, toggle] = useToggle();` and can attach `toggle` to a button's `onClick`. The functional state update calculates the next value from the pending previous value, making it reliable when React batches updates. The `initial` argument supplies the initial state; changing that argument later does not automatically reset existing state.

Under the hood, a custom hook does not create a separate component or an independent rendering boundary. Its built-in hooks participate in the calling component's hook sequence, and React associates their state with that component instance and their call order. Therefore, call custom hooks at the top level of function components or other custom hooks, not inside conditions, loops, event handlers, or ordinary utility functions. Two calls to `useToggle` create independent state, even within one component. A custom hook shares stateful logic, not state; shared state requires a separate mechanism, such as lifted state, context, or an external store.

In interviews, explain the hook's contract, demonstrate its usage, and identify whether it needs effects or cleanup. A toggle needs neither. If a hook subscribes to browser events or another external source, its effect should include the appropriate dependencies and return cleanup to remove the subscription. Interviewers look for correct hook placement, predictable inputs and outputs, and awareness of stale closures. Keep the abstraction focused, and add memoisation only when a concrete consumer benefits from stable references.

Key points to remember

  • Name the function with `use` followed by a capital letter and compose React hooks inside it.
  • Accept configuration as arguments and return the values or actions callers need.
  • Call custom hooks only at the top level of function components or other hooks.
  • Each call has independent local hook state; reusing the hook does not share that state.
  • Use functional updates for previous-state calculations and clean up effect-based subscriptions.

Common mistakes candidates make

  • Calling a custom hook conditionally or inside an event handler.
  • Assuming two components using the same custom hook automatically share its local state.
  • Expecting a changed initial-value argument to reset state after the first render.

Likely follow-up questions

How is a custom hook different from a utility function?

A custom hook can call React hooks and participate in a component's state and lifecycle behaviour, so its call sites must follow the Rules of Hooks. An ordinary utility function does not call hooks and can generally be invoked wherever its calculation is needed.

Should the returned toggle function use useCallback?

Not automatically: the inline function is correct but has a new identity on every render. Use `useCallback(() => setOn(o => !o), [])` when stable identity matters, such as when passing it to a memoised child.

How can multiple components share state through a custom hook?

Keep the state in a shared owner, such as a context provider or external store, and let the custom hook read or update that source. The shared owner provides the shared state; the hook provides a reusable access interface.

Interview tip: Show the small `useToggle` implementation, explain the functional update, and explicitly state that custom hooks share logic rather than local state.

Related Interview Questions

1
ReactIntermediate#effects#data

How do you fetch data in a React component?

Open
2
ReactAdvanced#effects#debugging

What causes an infinite re-render loop?

Open
3
ReactIntermediate#state#patterns

What is lifting state up?

Open