Rules of HooksLink for this heading

January 6, 2025 · View on GitHub

Hooks are defined using JavaScript functions, but they represent a special type of reusable UI logic with restrictions on where they can be called.


Functions whose names start with use are called Hooks in React.

Don’t call Hooks inside loops, conditions, nested functions, or try/catch/finally blocks. Instead, always use Hooks at the top level of your React function, before any early returns. You can only call Hooks while React is rendering a function component:

function Counter() {

  // ✅ Good: top-level in a function component

  const [count, setCount] = useState(0);

  // ...

}

function useWindowWidth() {

  // ✅ Good: top-level in a custom Hook

  const [width, setWidth] = useState(window.innerWidth);

  // ...

}

It’s not supported to call Hooks (functions starting with use) in any other cases, for example:

  • 🔴 Do not call Hooks inside conditions or loops.
  • 🔴 Do not call Hooks after a conditional return statement.
  • 🔴 Do not call Hooks in event handlers.
  • 🔴 Do not call Hooks in class components.
  • 🔴 Do not call Hooks inside functions passed to useMemo, useReducer, or useEffect.
  • 🔴 Do not call Hooks inside try/catch/finally blocks.

If you break these rules, you might see this error.

function Bad({ cond }) {

  if (cond) {

    // 🔴 Bad: inside a condition (to fix, move it outside!)

    const theme = useContext(ThemeContext);

  }

  // ...

}

function Bad() {

  for (let i = 0; i < 10; i++) {

    // 🔴 Bad: inside a loop (to fix, move it outside!)

    const theme = useContext(ThemeContext);

  }

  // ...

}

function Bad({ cond }) {

  if (cond) {

    return;

  }

  // 🔴 Bad: after a conditional return (to fix, move it before the return!)

  const theme = useContext(ThemeContext);

  // ...

}

function Bad() {

  function handleClick() {

    // 🔴 Bad: inside an event handler (to fix, move it outside!)

    const theme = useContext(ThemeContext);

  }

  // ...

}

function Bad() {

  const style = useMemo(() => {

    // 🔴 Bad: inside useMemo (to fix, move it outside!)

    const theme = useContext(ThemeContext);

    return createStyle(theme);

  });

  // ...

}

class Bad extends React.Component {

  render() {

    // 🔴 Bad: inside a class component (to fix, write a function component instead of a class!)

    useEffect(() => {})

    // ...

  }

}

function Bad() {

  try {

    // 🔴 Bad: inside try/catch/finally block (to fix, move it outside!)

    const [x, setX] = useState(0);

  } catch {

    const [x, setX] = useState(1);

  }

}

You can use the eslint-plugin-react-hooks plugin to catch these mistakes.

Note

Custom Hooks may call other Hooks (that’s their whole purpose). This works because custom Hooks are also supposed to only be called while a function component is rendering.


Don’t call Hooks from regular JavaScript functions. Instead, you can:

✅ Call Hooks from React function components. ✅ Call Hooks from custom Hooks.

By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.

function FriendList() {

  const [onlineStatus, setOnlineStatus] = useOnlineStatus(); // ✅

}

function setOnlineStatus() { // ❌ Not a component or custom Hook!

  const [onlineStatus, setOnlineStatus] = useOnlineStatus();

}

PreviousReact calls Components and Hooks


Copyright © Meta Platforms, Inc

no uwu plz

uwu?

Logo by@sawaratsuki1004

Learn React

Quick Start

Installation

Describing the UI

Adding Interactivity

Managing State

Escape Hatches

API Reference

React APIs

React DOM APIs

Community

Code of Conduct

Meet the Team

Docs Contributors

Acknowledgements

More

Blog

React Native

Privacy

Terms

On this page


React

v19

Search⌘CtrlK

Learn

Reference

Community

Blog

Is this page useful?

API Reference

Overview