Skip to the solution
EasyFrontend6 min read

What are React Hooks? Name a few common ones.

1.1k views

The problem

Question presented to candidate: "What are Hooks, why were they introduced, and which ones do you actually reach for?"

What a strong answer should cover:

  • Hooks are functions that let a function component use React features β€” state, effects, context, refs β€” that previously required a class.
  • Introduced in React 16.8 (2019). The motivation: sharing stateful logic was only possible via HOCs and render props, both of which added wrapper components.
  • The Rules of Hooks: call them unconditionally, at the top level, and only from a component or another hook.
  • The common ones, grouped: useState/useReducer (state), useEffect/useLayoutEffect (effects), useContext (context), useRef (persistent values and DOM), useMemo/useCallback (memoisation).
  • Modern additions worth naming: useTransition, useDeferredValue, useSyncExternalStore, useId, and the React 19 set β€” useActionState, useOptimistic, useEffectEvent.
  • Custom hooks are the payoff: any use-prefixed function composing other hooks.
  • They did not replace classes for everything β€” Error Boundaries still need one.

Clarifying questions expected:

  • "Do you want the full list, or the ones I use day to day?"

Code / implementation expected: Optional. A component using two or three hooks together is enough.

  • hooks
  • functional components
  • state
  • side effects

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

6 min read Β· 9 sections

Try it in the playground

Open any example in the playground to run and change it.

ReactSix common hooks working together in one small component
import {
  useState, useEffect, useRef, useMemo, useCallback, useId, useContext, createContext,
} from "react";

const ThemeContext = createContext("light");

// A custom hook: composes two built-ins, shares logic with no wrapper component.
function useDebounced(value, ms) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setDebounced(value), ms);
    return () => clearTimeout(id); // cleanup cancels the pending timer
  }, [value, ms]);
  return debounced;
}

const FRUIT = ["apple", "apricot", "banana", "blackberry", "cherry", "cranberry", "date"];

function Search() {
  const [query, setQuery] = useState("");          // useState  β€” local state
  const theme = useContext(ThemeContext);          // useContext β€” shared value
  const inputId = useId();                         // useId      β€” stable SSR-safe id
  const renders = useRef(0);                       // useRef     β€” persists, no re-render
  renders.current++;

  const debounced = useDebounced(query, 300);      // the custom hook

  // useMemo β€” recompute only when the debounced query actually changes.
  const results = useMemo(
    () => FRUIT.filter((f) => f.startsWith(debounced.toLowerCase())),
    [debounced],
  );

  // useCallback β€” a stable identity, safe to pass to a memoised child.
  const clear = useCallback(() => setQuery(""), []);

  return (
    <div style={{ color: theme === "dark" ? "#eee" : "#111" }}>
      <label htmlFor={inputId}>Filter fruit: </label>
      <input id={inputId} value={query} onChange={(e) => setQuery(e.target.value)} />{" "}
      <button onClick={clear}>clear</button>

      <p style={{ fontSize: 13, color: "#666" }}>
        typed: <strong>{query || "(empty)"}</strong> Β· debounced:{" "}
        <strong>{debounced || "(empty)"}</strong> Β· renders: <strong>{renders.current}</strong>
      </p>

      <ul>{results.map((r) => <li key={r}>{r}</li>)}</ul>
      {results.length === 0 && <p style={{ color: "#a33" }}>No matches.</p>}
    </div>
  );
}

export default function App() {
  return (
    <div style={{ padding: 24, fontFamily: "system-ui", lineHeight: 1.6 }}>
      <ThemeContext.Provider value="light">
        <Search />
      </ThemeContext.Provider>
      <p style={{ color: "#666", fontSize: 13 }}>
        Type quickly: the debounced value lags 300ms behind, and the filter only
        recomputes when it settles. The render counter comes from a ref, so
        reading it never causes a render of its own.
      </p>
    </div>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 2 of 119 in React.js

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All React.js questions
Up nextEasy

What is `PropTypes` and when would you use it?

Continue