Skip to main content

Rules of hooks

Two main rules of hooks

1. Call hooks only at the top level

Do not call hooks inside conditions, loops, or nested functions. Hooks must be called always in the same order on every render.

javascript
// Bad if (isVisible) { const [count, setCount] = useState(0); // breaks the rule! } // Good const [count, setCount] = useState(0); if (isVisible) { // just use count }

Why this matters so much: React determines which state belongs to which hook by call order. If the order changes (for example, because of an if), React will "mix up" the states.


2. Call hooks only in functional components or custom hooks

You cannot call hooks outside a component. Hooks can be called:

  • inside a functional component
  • or inside a custom hook (a function whose name starts with use)
javascript
// Bad useState(); // outside a component - an error // Good function MyComponent() { const [value, setValue] = useState(0); } // Good (custom hook) function useCounter() { const [count, setCount] = useState(0); return [count, setCount]; }

Additional good practices

3. A custom hook's name must start with use

This is needed so React understands that it's a hook (for example, for linting).

javascript
function useLocalStorage(key, initialValue) { ... } // yes function localStorageHook(key, initialValue) { ... } // no

4. Pass dependencies correctly in useEffect, useMemo, useCallback

javascript
useEffect(() => { fetchData(id); }, [id]); // id is the dependency

If you skip a dependency, the code may use stale values and behave unpredictably.


5. Don't call hooks inside ordinary JS functions

If you need to reuse logic, make a custom hook:

javascript
// Bad function fetchUser() { const [user, setUser] = useState(null); // not allowed } // Good function useUser() { const [user, setUser] = useState(null); return user; }

React helps you follow these rules

React ships with a linter: eslint-plugin-react-hooks It automatically checks:

  • the order in which hooks are called,
  • the correctness of dependencies in useEffect.
javascript
npm install eslint-plugin-react-hooks --save-dev

In .eslintrc:

javascript
{ "plugins": ["react-hooks"], "rules": { "react-hooks/rules-of-hooks": "error", "react-hooks/exhaustive-deps": "warn" } }

Short summary

RuleWhy
Hooks are called only at the top levelSo the call order doesn't change
Hooks are called only in components or hooksSo React can track state
Custom hooks start with useFor readability and linter checks
Correct dependencies in useEffect/useMemo/useCallbackTo avoid using stale values
Use ESLint rulesSo React itself flags mistakes

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.