🇬🇧 Limited Time — UK Only·🎓 Free Learning for 1 Month·🤖 Free AI Training Included·📚 4,000+ Lessons · 35,000+ Quizzes·🏆 GCSE Mocks · Olympiad Papers·⚡ Selected Students Only · Limited Places·🎁 Free Value Worth £2,000·🇬🇧 Limited Time — UK Only·🎓 Free Learning for 1 Month·🤖 Free AI Training Included·📚 4,000+ Lessons · 35,000+ Quizzes·🏆 GCSE Mocks · Olympiad Papers·⚡ Selected Students Only · Limited Places·🎁 Free Value Worth £2,000·🇬🇧 Limited Time — UK Only·🎓 Free Learning for 1 Month·🤖 Free AI Training Included·📚 4,000+ Lessons · 35,000+ Quizzes·🏆 GCSE Mocks · Olympiad Papers·⚡ Selected Students Only · Limited Places·🎁 Free Value Worth £2,000·
⚛️ React JS

Rules of hooks

📚 What are the Rules of Hooks? React hooks (useState, useEffect, useContext, etc.) have two strict rules that you MUST follow. Breaking these rules causes mysterious bugs where state gets mixed up between renders. React actually includes a linter rule (eslint-plugin-react-hooks) to catch violation…

8 min 10 XP Lesson 21 of 23
Rules of hooks
🌐

Appy Says…

React Hooks have two golden rules that sound restrictive but make perfect sense once you understand why. Break them and you'll get confusing bugs that are very hard to debug. Follow them and Hooks work flawlessly.

📖

What are the Rules of Hooks?

The two rules that React enforces for all hooks:

  • Rule 1 — Call Hooks at the top level: Never call hooks inside loops, conditions, or nested functions
  • Rule 2 — Call Hooks only from React functions: Only call hooks in function components or custom hooks — not regular JS functions
  • Bad: if (isLoggedIn) { const [user] = useState(null); }
  • Good: const [user] = useState(null); if (isLoggedIn) { /* use user */ }
  • The ESLint plugin eslint-plugin-react-hooks enforces both rules automatically
  • React tracks hooks by their call order — the same hooks must be called every render
🎮

Think of it like Minecraft redstone rules

Redstone has rules: power travels exactly 15 blocks; comparators face a specific way; some blocks need to update in a specific order. Break the rules and circuits behave unpredictably. React's hook order is its redstone contract — call them consistently, same order, every render.

⚙️

How It Works

  • 1. React stores hook state in an internal array per component
  • 2. On render 1: [state1, state2, state3] — each useState gets slot 0, 1, 2
  • 3. On render 2: React reads the same slots in the same order
  • 4. If a hook is inside a condition: render 1 may call 3 hooks; render 2 may call 2 — slots misalign
  • 5. This causes the wrong state to be read for each hook
  • 6. React's lint rule catches this at dev-time before it can cause runtime bugs
🌍

Real-World Examples

  • Bad: if (showSearch) { const [query, setQuery] = useState(''); } — breaks hook order
  • Good: const [query, setQuery] = useState(''); // use only when showSearch is true
  • Bad: calling useState inside a forEach callback
  • Good: extract to a custom hook if you need per-item state
💡

Key Facts

  • React 18.2 added a new lint rule for exhaustive-deps — another hook rule for useEffect
  • The rules are enforced by the eslint-plugin-react-hooks package (bundled in Create React App and Vite)
  • Custom hooks MUST start with 'use' — this is how React identifies them for the linter
  • React Compiler (React 19+) enforces hook rules at compile time
⚠️

Watch Out!

The most common hook rule violation: calling useEffect inside a conditional. If you need different effects for different conditions, use one useEffect with an if inside the body — not multiple conditional useEffects.

📌

Remember

Rule 1: Hooks at top level — never inside if/for/nested functions. Rule 2: Hooks only in React function components or custom hooks. Install eslint-plugin-react-hooks and it will catch violations automatically.

What You Learned

  • Two rules: call hooks only at top level (not inside conditions/loops); only in React function components or custom hooks
  • React tracks hooks by call order — any conditional call misaligns the slot array causing bugs
  • Unlocks: bug-free hook usage, understanding why hooks work the way they do

Key Facts

  • React 18.2 added a new lint rule for exhaustive-deps — another hook rule for useEffect
  • The rules are enforced by the eslint-plugin-react-hooks package (bundled in Create React App and Vite)
  • Custom hooks MUST start with 'use' — this is how React identifies them for the linter
  • React Compiler (React 19+) enforces hook rules at compile time

Real-World Examples

• Bad: <code>if (showSearch) { const [query, setQuery] = useState(''); }</code> — breaks hook order • Good: <code>const [query, setQuery] = useState(''); // use only when showSearch is true</code> • Bad: calling useState inside a forEach callback • Good: extract to a custom hook if you need per-item state

Remember

Rule 1: Hooks at top level — never inside if/for/nested functions. Rule 2: Hooks only in React function components or custom hooks. Install eslint-plugin-react-hooks and it will catch violations automatically.

Quick Quiz

1 / 2

Hooks must be called?