askill
following-the-rules-of-hooks

following-the-rules-of-hooksSafety 95Repository

Fix React Rules of Hooks violations - conditional calls, hooks in loops/callbacks/classes

0 stars
1.2k downloads
Updated 11/25/2025

Package Files

Loading files...
SKILL.md

Rules of Hooks

React enforces two invariants on Hook usage. Violating these causes state corruption and unpredictable behavior.

The Rules

  1. Top-level only - Never call Hooks inside loops, conditions, nested functions, or try/catch/finally
  2. React functions only - Call Hooks exclusively from function components or custom Hooks

Why: Consistent call order across renders; conditional/dynamic invocation breaks state tracking.

Valid Hook Locations

✅ Top level of function components ✅ Top level of custom Hooks (use* functions)

function Counter() {
  const [count, setCount] = useState(0);
  return <div>{count}</div>;
}

function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);
  return width;
}

Common Violations

ViolationWhy InvalidFix
Inside if/elseSkipped on some rendersMove to top; use conditional rendering
Inside loopsVariable call countMove to top; manage array state
After early returnUnreachable on some pathsMove Hook before return
In event handlersCalled outside renderMove to top; use state from closure
In class componentsClasses don't support HooksConvert to function component
Inside callbacksNested function contextMove Hook to top level

Common Fixes

Conditional Hooks

Wrong:

function Profile({ userId }) {
  if (userId) {
    const user = useUser(userId);
  }
}

Right:

function Profile({ userId }) {
  const user = useUser(userId);
  if (!userId) return null;
  return <div>{user.name}</div>;
}

Pattern: Always call Hook, use conditional rendering for output.

Hooks in Loops

Wrong:

function List({ items }) {
  return items.map(item => {
    const [selected, setSelected] = useState(false);
    return <Item selected={selected} />;
  });
}

Right:

function List({ items }) {
  const [selected, setSelected] = useState({});
  return items.map(item => (
    <Item
      key={item.id}
      selected={selected[item.id]}
      onToggle={() => setSelected(s => ({...s, [item.id]: !s[item.id]}))}
    />
  ));
}

Pattern: Single Hook managing collection, not per-item Hooks.

Hooks in Event Handlers

Wrong:

function Form() {
  function handleSubmit() {
    const [loading, setLoading] = useState(false);
    setLoading(true);
  }
  return <button onClick={handleSubmit}>Submit</button>;
}

Right:

function Form() {
  const [loading, setLoading] = useState(false);
  function handleSubmit() {
    setLoading(true);
  }
  return <button onClick={handleSubmit} disabled={loading}>Submit</button>;
}

Pattern: Hook at component level, setter in handler.

Hooks in Classes

Wrong:

function BadCounter() {
  const [count, setCount] = useState(0);
  return <div>{count}</div>;
}

Right:

function Counter() {
  const [count, setCount] = useState(0);
  return <div>{count}</div>;
}

Pattern: Use function components for Hooks.

Hooks in Callbacks

Wrong:

function Theme() {
  const style = useMemo(() => {
    const theme = useContext(ThemeContext);
    return createStyle(theme);
  }, []);
}

Right:

function Theme() {
  const theme = useContext(ThemeContext);
  const style = useMemo(() => createStyle(theme), [theme]);
}

Pattern: Call Hook at top level, reference in callback.

Hooks After Early Returns

Wrong:

function User({ userId }) {
  if (!userId) return null;
  const user = useUser(userId);
  return <div>{user.name}</div>;
}

Right:

function User({ userId }) {
  const user = useUser(userId || null);
  if (!userId) return null;
  return <div>{user.name}</div>;
}

Pattern: Call all Hooks before any returns.

Custom Hooks

Custom Hooks may call other Hooks because they execute during render phase:

function useDebounce(value, delay) {
  const [debounced, setDebounced] = useState(value);
  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);
  return debounced;
}

Requirements: Name starts with use; called from function component or another custom Hook; follows same Rules of Hooks.

Quick Diagnostic

ESLint error: "React Hook cannot be called..."

  1. Check location: Is Hook inside if/loop/try/handler/class?
  2. Move Hook to top level of component/custom Hook
  3. Keep conditional logic, move Hook call outside it
  4. Use conditional rendering, not conditional Hooks

Reference: https://react.dev/reference/rules/rules-of-hooks

Install

Download ZIP
Requires askill CLI v1.0+

AI Quality Score

90/100Analyzed 2/19/2026

High-quality technical skill about React Rules of Hooks with excellent code examples, clear explanations of violations and fixes, comprehensive table of common violations, and actionable diagnostic steps. Well-organized in dedicated skills folder with structured examples for each violation type (conditional, loops, handlers, callbacks, early returns). No tags present but content is accurate, dense, and highly reusable across React projects.

95
90
88
87
92

Metadata

Licenseunknown
Version1.0.0
Updated11/25/2025
Publisherdjankies

Tags

No tags yet.