Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
State  ›  Lesson

The Rules of Hooks

Hooks Best Practices 12 minHooks must be called at the top level of a component or custom hook, in the same order on every render, never inside conditions, loops or nested functions.

The Rules of Hooks

useState is a hook: a function whose name starts with use and that plugs your component into a React feature. You will meet several more — useReducer, useContext, useEffect, useRef. They are powerful, and they come with two short rules that keep them from breaking in confusing ways.

The rule

Top level, same order, every render — and only in components or hooks.

Top level. Call hooks directly in the body of the component, before any early return. Never inside if, loops, nested functions or event handlers.

function BookCard({ book }) {
  const [open, setOpen] = useState(false); // ✓ top level

  if (!book) return null;                  // early return comes after hooks

  // ✗ if (book.read) { const [x, setX] = useState(0); }
  // ✗ function handleClick() { useState(0); }

  return <article onClick={() => setOpen(!open)}>{book.title}</article>;
}

Same order, every render. Why the fuss? React does not know your variable names. It stores hook data in a list and hands it back by position: "first hook call gets slot 1, second gets slot 2." If a hook is skipped on one render, every hook after it receives the wrong slot.

Only in components or hooks. Call hooks from function components or from your own custom hooks (functions named useSomething, covered later). Not from ordinary helper functions or class components.

The official ESLint plugin, eslint-plugin-react-hooks, catches these mistakes as you type, and the Vite template includes it.

A few habits that go with the rules:

  • Keep state minimal. Do not store what you can calculate. If you have books, compute books.length during render instead of keeping a count state that can drift out of sync.
  • Name setters clearly. [isOpen, setIsOpen], [books, setBooks].
  • Let the linter warn you rather than silencing it.

The shortcut

Picture the hooks as a numbered queue at the top of the function. Every render must pass the same numbered hooks in the same order before anything can branch.

Why a skipped hook breaks thingsStep 1 of 4
  1. Render 1

    book.read is true: hooks run as #1 open, #2 rating, #3 note.

Drills

Answer fast — trust the rule.

quick drill

Where may useState be called?

quick drill

How does React match each useState call to its stored value?

quick drill

A component has if (loading) return <Spinner />; followed by useState. What is the problem?

quick drill

A component keeps books in state and also count in state, updating both when a book is added. What is better?

Remember

  • Top level, same order, every render — only in components or custom hooks.
  • Picture a numbered queue of hooks before any branch.
  • Trap: hooks after an early return, and storing values you could compute.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainThe conditional hook

A component reads if (!book) return null; and then calls const [open, setOpen] = useState(false); below it. Explain which rule this breaks, why React cares, and how to fix it.