tezvyn:

Rules of Hooks: Call Order Is Sacred

AI-drafted, machine-checkedintermediate

Hook calls must keep the same order every render because React maps them to state by array index. Only call hooks at the top level of React functions. Break the order and React desyncs, producing stale state or crashes.

WHY IT EXISTS: Before hooks, React class components stored state on the instance and lifecycle methods were explicit. Functional components were purely stateless. Hooks were invented to give functional components the same powers without rewriting them as classes, but React needed a way to attach persistent state to a function that gets re-invoked every render. Since functions have no stable instance reference that survives re-execution, React needed a mechanism outside the component to remember which piece of state belonged to which call.

THE MENTAL MODEL: Imagine a spreadsheet where each row is a hook and the row number is its identity. On every render, React reads down the sheet line by line. If you insert or delete a row in the middle, every row below it shifts and the data in column two gets read as if it were column three. Hooks are not normal utility functions you can call conditionally or inside loops. They are declarations of stateful dependencies that must be registered in the exact same sequence every time so React's internal ledger stays aligned with your component.

HOW IT WORKS: React stores hook state in a linked list attached to the fiber node representing your component. When your component runs, React walks that list in order. The first hook call maps to the first node, the second to the second, and so on. The rules enforce this: only call hooks from React functions, and only at the top level. Calling inside an if block means the hook might execute on render one but skip on render two, so React thinks the next hook is the previous one. The ESLint plugin react-hooks/rules-of-hooks exists precisely to catch these violations at build time before they corrupt runtime state.

WHEN TO USE IT: You are following the rules whenever you write useState, useEffect, or custom hooks at the top scope of a component or custom hook body, before any early return. This applies to every functional component that manages state, performs data fetching, subscribes to events, or holds refs. The rules are not optional conventions; they are structural requirements for React's reconciliation engine.

WHEN NOT TO USE IT: Do not call hooks inside loops, conditions, or nested functions. Do not call them after an early return in your component. Do not call them from regular JavaScript functions that are not components or custom hooks. If you need conditional logic, move the condition inside the hook or inside the hook's callback, not around the hook call itself.

ONE CANONICAL EXAMPLE: A common mistake is writing a component that calls useEffect only if a prop exists. A developer writes if userId then useEffect to avoid fetching when userId is null. On the first render userId is present so the effect hook is first in the list. On the next render userId is null so the hook is skipped. React now treats the next hook, perhaps a useState, as if it were the effect hook. The result is a corrupted component state or a crash. The correct pattern is to always call useEffect and check userId inside the effect body, or to return early before any hooks are called.

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.