Rules
rules-of-hooks
Full Name in @eslint-react/eslint-plugin
@eslint-react/hooks-extra/rules-of-hooksFull Name in eslint-plugin-react-hooks-extra
react-hooks-extra/rules-of-hooksPresets
Not included in any preset.
Description
Enforces the Rules of Hooks.
React Hooks must be called at the top level of a React function component or a custom Hook. They must not be called inside conditions, loops, nested functions, after early returns, in async functions, in class components, or at module level.
The special use() hook is an exception — it is allowed inside conditionals and loops, but not inside try/catch blocks.
Examples
Passing
import { useState, useEffect } from "react";
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log(count);
}, [count]);
return <div>{count}</div>;
}Passing
import { useState } from "react";
function useCustomHook() {
const [value, setValue] = useState("");
return [value, setValue] as const;
}Passing
import { use } from "react";
function MyComponent({ shouldFetch, promise }) {
if (shouldFetch) {
const data = use(promise);
return <div>{data}</div>;
}
return <div>No data</div>;
}Failing
import { useState } from "react";
function MyComponent({ condition }) {
// 🔴 React Hook 'useState' is called conditionally.
if (condition) {
const [value, setValue] = useState("");
}
return null;
}Failing
import { useEffect } from "react";
function MyComponent({ items }) {
// 🔴 React Hook 'useEffect' may be executed more than once.
for (const item of items) {
useEffect(() => {
console.log(item);
}, [item]);
}
return null;
}Failing
import { useState, useEffect } from "react";
function MyComponent({ condition }) {
if (condition) {
return null;
}
// 🔴 React Hook 'useState' is called after an early return.
const [value, setValue] = useState("");
return <div>{value}</div>;
}Failing
import { useState } from "react";
function MyComponent() {
const handleClick = () => {
// 🔴 React Hook 'useState' is called in a nested function.
const [value, setValue] = useState("");
};
return <button onClick={handleClick}>Click</button>;
}Failing
import { useState } from "react";
// 🔴 React Hook 'useState' is called in an async function.
async function useAsyncHook() {
const [value, setValue] = useState("");
return value;
}Failing
import { useState } from "react";
class MyComponent {
render() {
// 🔴 React Hook 'useState' cannot be called in a class component.
const [value, setValue] = useState("");
return null;
}
}Failing
import { useState } from "react";
// 🔴 React Hook 'useState' cannot be called at the top level.
const [value, setValue] = useState("");Failing
import { use } from "react";
function MyComponent({ promise }) {
try {
// 🔴 React Hook 'use' cannot be called inside a try/catch block.
const data = use(promise);
return <div>{data}</div>;
} catch (e) {
return <div>Error</div>;
}
}