验证组件和钩子是否遵循 钩子的规则。
¥Validates that components and hooks follow the Rules of Hooks.
规则详情
¥Rule Details
React 依赖于钩子的调用顺序来正确保存渲染之间的状态。每次组件渲染时,React 都期望以完全相同的顺序调用相同的钩子。当有条件地或在循环中调用钩子时,React 会丢失哪个状态对应于哪个钩子调用的跟踪,从而导致状态不匹配和 “渲染的钩子数量少于/多于预期” 错误等错误。
¥React relies on the order in which hooks are called to correctly preserve state between renders. Each time your component renders, React expects the exact same hooks to be called in the exact same order. When hooks are called conditionally or in loops, React loses track of which state corresponds to which hook call, leading to bugs like state mismatches and “Rendered fewer/more hooks than expected” errors.
常见违规
¥Common Violations
这些模式违反了钩子规则:
¥These patterns violate the Rules of Hooks:
-
条件中的钩子(
if
/else
、三元组、&&
/||
)¥Hooks in conditions (
if
/else
, ternary,&&
/||
) -
循环中的钩子(
for
、while
、do-while
)¥Hooks in loops (
for
,while
,do-while
) -
提前返回后的钩子
¥Hooks after early returns
-
回调/事件处理程序中的钩子
¥Hooks in callbacks/event handlers
-
异步函数中的钩子
¥Hooks in async functions
-
类方法中的钩子
¥Hooks in class methods
-
模块级钩子
¥Hooks at module level
无效
¥Invalid
此规则的错误代码示例:
¥Examples of incorrect code for this rule:
// ❌ Hook in condition
if (isLoggedIn) {
const [user, setUser] = useState(null);
}
// ❌ Hook after early return
if (!data) return <Loading />;
const [processed, setProcessed] = useState(data);
// ❌ Hook in callback
<button onClick={() => {
const [clicked, setClicked] = useState(false);
}}/>
// ❌ `use` in try/catch
try {
const data = use(promise);
} catch (e) {
// error handling
}
// ❌ Hook at module level
const globalState = useState(0); // Outside component
有效
¥Valid
此规则的正确代码示例:
¥Examples of correct code for this rule:
function Component({ isSpecial, shouldFetch, fetchPromise }) {
// ✅ Hooks at top level
const [count, setCount] = useState(0);
const [name, setName] = useState('');
if (!isSpecial) {
return null;
}
if (shouldFetch) {
// ✅ `use` can be conditional
const data = use(fetchPromise);
return <div>{data}</div>;
}
return <div>{name}: {count}</div>;
}
故障排除
¥Troubleshooting
我想要根据某些条件获取数据
¥I want to fetch data based on some condition
你正在尝试有条件地调用 useEffect:
¥You’re trying to conditionally call useEffect:
// ❌ Conditional hook
if (isLoggedIn) {
useEffect(() => {
fetchUserData();
}, []);
}
无条件调用钩子,并检查内部条件:
¥Call the hook unconditionally, check condition inside:
// ✅ Condition inside hook
useEffect(() => {
if (isLoggedIn) {
fetchUserData();
}
}, [isLoggedIn]);
我需要针对不同场景使用不同的状态
¥I need different state for different scenarios
你正在尝试有条件地初始化状态:
¥You’re trying to conditionally initialize state:
// ❌ Conditional state
if (userType === 'admin') {
const [permissions, setPermissions] = useState(adminPerms);
} else {
const [permissions, setPermissions] = useState(userPerms);
}
始终调用 useState,并有条件地设置初始值:
¥Always call useState, conditionally set the initial value:
// ✅ Conditional initial value
const [permissions, setPermissions] = useState(
userType === 'admin' ? adminPerms : userPerms
);
选项
¥Options
你可以使用共享的 ESLint 设置(在 eslint-plugin-react-hooks
6.1.1 及更高版本中可用)配置自定义效果钩子:
¥You can configure custom effect hooks using shared ESLint settings (available in eslint-plugin-react-hooks
6.1.1 and later):
{
"settings": {
"react-hooks": {
"additionalEffectHooks": "(useMyEffect|useCustomEffect)"
}
}
}
-
additionalEffectHooks
:用于匹配自定义钩子的正则表达式模式,这些钩子应该被视为效果。这允许从自定义效果钩子中调用useEffectEvent
和类似的事件函数。¥
additionalEffectHooks
: Regex pattern matching custom hooks that should be treated as effects. This allowsuseEffectEvent
and similar event functions to be called from your custom effect hooks.
此共享配置由 rules-of-hooks
和 exhaustive-deps
规则使用,以确保所有与钩子相关的 linting 行为一致。
¥This shared configuration is used by both rules-of-hooks
and exhaustive-deps
rules, ensuring consistent behavior across all hook-related linting.