react-hooks/hooks
Require hooks to be called at the top level of a component or hook, never conditionally
Also called react_hooks/hooks, react/hooks
React tells one useState from the next by the order the hooks are called in. That order must be the same on every render. A hook inside an if, a loop, or after an early return runs on some renders and not on others. Then state ends up with the wrong hook, or React throws.
The rule also reports a hook that's called inside a nested function, and a hook that's passed around as a value instead of being called.
Configure#
Off by default. To turn it on:
bunfig.toml
[lint.rules]
"react-hooks/hooks" = "error" # or "warn"Examples#
example.jsx1 problem
import { useState } from "react";
function Profile({ user }) {
if (!user) {
return null;
}
const [name, setName] = useStateError: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (react.dev/warnings/invalid-hook-call-warning)(user.name);
return <input value={name} onChange={event => setName(event.target.value)} />;
}example.jsx1 problem
import { useState } from "react";
function UserList({ users }) {
const rows = users.map(user => {
const [open] = useStateError: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (react.dev/warnings/invalid-hook-call-warning)Cannot call useState within a function expression.(false);
return <li key={user.id}>{open ? user.bio : user.name}</li>;
});
return <ul>{rows}</ul>;
}example.jsx4 problems
import { useState } from "react";
import { useStoredState } from "./storage";
function Field({ persist }) {
const useValue = persist ? Error: Hooks may not be referenced as normal values, they must be called. See react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-valuesuseStoredStateError: Hooks may not be referenced as normal values, they must be called. See react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-valuesError: Hooks may not be referenced as normal values, they must be called. See react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values : useStateError: Hooks may not be referenced as normal values, they must be called. See react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-valuesError: Hooks may not be referenced as normal values, they must be called. See react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values;
const [value] = useValueError: Hooks may not be referenced as normal values, they must be called. See react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values("");
return <input value={value} readOnly />;
}example.jsxNo problems
import { useState } from "react";
function Profile({ user }) {
const [name, setName] = useState(user ? user.name : "");
if (!user) {
return null;
}
return <input value={name} onChange={event => setName(event.target.value)} />;
}When not to use it#
react-hooks/rules-of-hooks finds most of the same mistakes and is on by default in React projects. You rarely need both.