After this lesson, you will be able to: Use every common hook correctly: useState, useEffect, useContext, useReducer, useRef, useMemo, useCallback, useTransition, useDeferredValue.
Hooks are simple by themselves; combinations + dependency arrays are where bugs live.
The basics; get them right.
const [count, setCount] = useState(0);// Effect, synchronizes with external systemsuseEffect(() => {document.title = `Count: ${count}`;return () => { document.title = "App"; }; // cleanup}, [count]);// Dependency array tells React WHEN to re-run.// [] = once on mount.// no array = every render (almost never what you want).// [count] = whenever count changes.
Cache expensive computations + stable function refs.
// Cache the result of an expensive sortconst sorted = useMemo(() => items.sort((a, b) => a.x - b.x), [items]);// Stable callback reference (matters for child memoization or effect deps)const handleClick = useCallback((id: string) => setSelected(id), []);// Don't wrap everything in useMemo/useCallback. They have their own cost. Use when:// - Computation is genuinely slow (>5ms)// - You pass a function/object as a prop to a memoized child// - You depend on the ref in another hook's deps
State machine pattern.
type State = { count: number; user: User | null };type Action = { type: "inc" } | { type: "set-user"; user: User };function reducer(s: State, a: Action): State {switch (a.type) {case "inc": return { ...s, count: s.count + 1 };case "set-user": return { ...s, user: a.user };}}const [state, dispatch] = useReducer(reducer, { count: 0, user: null });dispatch({ type: "inc" });
Mark updates as low-priority.
const [isPending, startTransition] = useTransition();const [query, setQuery] = useState("");function onInput(e) {// Update input immediately (urgent)// Mark expensive list-filter as transition (interruptible)startTransition(() => setQuery(e.target.value));}// In the consumer: useDeferredValueconst deferredQuery = useDeferredValue(query);// Heavy filter uses deferredQuery; recent input keeps UI responsive.
Missing dependencies in useEffect. ESLint's `react-hooks/exhaustive-deps` rule is your friend; don't disable. useMemo/useCallback on every prop. Pure overhead unless there's a concrete reason. Conditional hook calls. Hooks must run in the same order every render. Setting state in an effect that depends on that state. Infinite render loop.
Pick the senior answer.
Sign in and purchase access to unlock this lesson.