> For AI agents: the complete documentation index is available at https://rslint.rs/llms.txt, the full documentation bundle is available at https://rslint.rs/llms-full.txt.

# rules-of-hooks

[Added in v0.5.1](https://github.com/web-infra-dev/rslint/releases/tag/v0.5.1)
## Configuration

| Preset                                 | Configured Value |
| -------------------------------------- | ---------------- |
| ✅ reactHooksPlugin.configs.recommended | `"error"`        |


```ts title=rslint.config.ts
import { defineConfig, reactHooksPlugin } from '@rslint/core';

export default defineConfig([
  reactHooksPlugin.configs.recommended,
  {
    rules: {
      'react-hooks/rules-of-hooks': 'error',
    },
  },
]);
```

Enforce React's Rules of Hooks: hooks must only be called at the top level of
React function components or custom Hooks, never inside loops, conditions,
nested functions, class components, or async functions.

## Rule Details

This rule reports React Hook calls that violate the [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks):

- A hook (a function whose name is `use` or starts with `use[A-Z0-9]`, or a
  member access like `Namespace.useFoo`) must be called at the top level of a
  function component or custom hook — never inside `if` / `else`, ternary
  expressions, `&&` / `||` / `??` chains, `try` / `catch` blocks, loops, or
  callbacks.
- A hook must not be called after an early `return` or `throw`.
- A hook must not be called inside a class component (method, accessor, or
  class-field arrow), inside an `async` function, or at the top level of a
  module.
- The React `use(...)` hook is exempt from the loop, conditional, and
  early-return checks (it may be called conditionally), but is still rejected
  inside `try` / `catch` blocks and async functions.
- Functions created with `useEffectEvent(...)` may only be called from inside
  a React effect hook (`useEffect`, `useLayoutEffect`, `useInsertionEffect`,
  or any hook matching the `additionalEffectHooks` setting) or another
  `useEffectEvent` callback in the same component.

Examples of **incorrect** code for this rule:

```javascript
function ComponentWithConditionalHook() {
  if (cond) {
    useConditionalHook();
  }
}

function ComponentWithHookInsideLoop() {
  while (cond) {
    useHookInsideLoop();
  }
}

function ComponentWithHookAfterEarlyReturn() {
  if (a) return;
  useState();
}

class ClassComponentWithHook extends React.Component {
  render() {
    React.useState();
  }
}

async function AsyncComponent() {
  useState();
}

function notAComponent() {
  useState();
}
```

Examples of **correct** code for this rule:

```javascript
function ComponentWithHook() {
  useHook();
}

function useCustomHook() {
  useState();
}

const FancyButton = React.forwardRef((props, ref) => {
  useHook();
  return <button {...props} ref={ref} />;
});

function App() {
  // `use(...)` may be called conditionally
  if (shouldShowText) {
    const text = use(query);
  }
}
```

## Options

`additionalHooks` is a regex of extra hook names to treat as effect hooks
(functions created with `useEffectEvent` may be called inside them):

```json
{
  "rules": {
    "react-hooks/rules-of-hooks": ["error", { "additionalHooks": "(useMyEffect|useServerEffect)" }]
  }
}
```

When set, the rule-level option takes precedence over the
`additionalEffectHooks` setting below.

## Settings

```json
{
  "settings": {
    "react-hooks": {
      "additionalEffectHooks": "(useMyEffect|useServerEffect)"
    }
  }
}
```

`additionalEffectHooks`
: A regular expression (matched against the bare hook name) that names extra
hooks for which `useEffectEvent`-bound identifiers may be referenced as
callbacks. Defaults to none.

## Original Documentation

- [react.dev — Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks)
- [Source code](https://github.com/facebook/react/blob/eslint-plugin-react-hooks@7.1.1/packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts)
