Custom Hooks

5 questions found

What is a custom hook in React and why would you create one?

Beginner
A custom hook is simply a JavaScript function whose name starts with use, and it lets you reuse stateful logic between different components without repeating the same code. It can call other hooks inside it, like useState or useEffect, just like a regular component can.
function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);
  useEffect(() => {
    function handleResize() { setWidth(window.innerWidth); }
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  return width;
}
Real-world example A shopping site uses a single useWindowWidth custom hook in both its navigation bar and its product grid, so both components can react to screen size changes without duplicating the same resize logic twice.

Common follow-ups: Why must a custom hook's name always start with the word use?;Can a custom hook call another custom hook inside it?

Hooks;Effects & Lifecycle

How would you write a custom hook to fetch data from an API and share that logic across components?

Intermediate
You move the fetching logic, along with loading and error state, inside a custom hook, and return whatever the component needs, such as the data, a loading flag, and any error. Every component that needs to fetch similar data can now reuse this one hook instead of repeating the same fetch code everywhere.
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url)
      .then((res) => res.json())
      .then((json) => { setData(json); setLoading(false); });
  }, [url]);

  return { data, loading };
}

const { data, loading } = useFetch('/api/products');
Real-world example A team building a dashboard reuses one useFetch custom hook across the users page, the orders page, and the reports page, avoiding writing the same fetch and loading logic three separate times.

Common follow-ups: How would you also handle errors properly inside this useFetch hook?;Why might using a library like React Query be better than writing your own fetch hook?

Data Fetching (React Query & SWR);Effects & Lifecycle

What are the rules you must follow when writing and using hooks, including custom hooks?

Intermediate
Hooks must always be called at the top level of a function component or another hook, never inside loops, conditions, or nested functions. This ensures React can correctly keep track of each hook's state between renders. Following this rule keeps custom hooks working reliably and predictably.
// Wrong, hook called conditionally
if (isLoggedIn) {
  useEffect(() => { /* ... */ }, []);
}

// Correct, hook always called, condition handled inside
useEffect(() => {
  if (isLoggedIn) { /* ... */ }
}, [isLoggedIn]);
Real-world example A developer fixes a confusing bug where a component's state seemed to mix up between renders, after discovering a hook was accidentally being called only under a certain condition instead of every single render.

Common follow-ups: Why does breaking this rule cause React to get confused about which state belongs to which hook?;What eslint plugin helps catch these mistakes automatically?

Hooks;React DevTools & Debugging

How would you build a custom hook that debounces a fast changing value, such as text typed into a search box?

Advanced
A debounce hook waits until the user has stopped typing for a short period before updating the final value, avoiding unnecessary work, like sending a network request, on every single keystroke.
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);
  return debouncedValue;
}

const debouncedSearch = useDebounce(searchText, 500);
Real-world example A search feature waits until a user pauses typing for half a second before actually sending a request to the server, using a useDebounce hook to avoid firing a network request on every single keystroke.

Common follow-ups: Why is clearing the timeout inside the cleanup function important for this hook to work correctly?;How would you write a similar hook that throttles instead of debounces?

Effects & Lifecycle;Data Fetching (React Query & SWR)

How is a custom hook different from a regular helper function?

Beginner
A custom hook can use other hooks like useState and useEffect internally, giving it access to a component's state and lifecycle, while a plain helper function cannot use hooks at all. If a function needs to remember values between renders or react to changes, it needs to be a hook and follow the rules of hooks.
// Plain function, no state or hooks involved
function formatPrice(amount) {
  return `$${amount.toFixed(2)}`;
}

// Custom hook, uses state internally
function useCounter() {
  const [count, setCount] = useState(0);
  return { count, increment: () => setCount(count + 1) };
}
Real-world example A team correctly writes formatPrice as a simple helper function since it does not need any state, but writes useCounter as a proper hook since it needs to remember and update a count value over time.

Common follow-ups: What error would you get if you tried to use useState inside a plain helper function?;How do you decide whether a piece of logic should become a custom hook or stay a regular function?

Hooks;Design Patterns in React