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) { ... } // no4. Pass dependencies correctly in useEffect, useMemo, useCallback
javascript
useEffect(() => {
fetchData(id);
}, [id]); // id is the dependencyIf 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-devIn .eslintrc:
javascript
{
"plugins": ["react-hooks"],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn"
}
}Short summary
| Rule | Why |
|---|---|
| Hooks are called only at the top level | So the call order doesn't change |
| Hooks are called only in components or hooks | So React can track state |
Custom hooks start with use | For readability and linter checks |
Correct dependencies in useEffect/useMemo/useCallback | To avoid using stale values |
| Use ESLint rules | So React itself flags mistakes |
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.