标准答案
- React 通过 Hooks 的调用顺序来记录 useState、useEffect、useRef 等 Hook 对应的内部状态。
- 条件语句、循环、嵌套函数和提前 return 可能让某次渲染少调用或多调用 Hook,破坏顺序。
- Hook 应写在组件函数或自定义 Hook 的顶层,不要写在 if、for、回调函数或普通工具函数里。
- 条件逻辑应该放到 Hook 内部,例如 useEffect 里判断条件,而不是条件性调用 useEffect。
- 自定义 Hook 也必须遵守同样规则,并且命名通常以 use 开头,方便 lint 规则识别。
题目解析
这道题的核心是调用顺序,而不是语法偏好。Hook 本质上需要在多次 render 之间找到同一份状态槽位。
eslint-plugin-react-hooks 能提前发现大多数违反规则的写法,团队项目应开启。
如果确实要按条件执行副作用,可以始终调用 Hook,在 Hook 的回调内部判断是否执行。
代码示例
下面展示错误写法和正确写法的区别。
TSX
function UserPanel({ enabled }: { enabled: boolean }) {
useEffect(() => {
if (!enabled) {
return
}
subscribeUser()
return unsubscribeUser
}, [enabled])
return <div>用户面板</div>
}常见误区
- 在 if 条件里调用 useEffect 或 useState。
- 在事件处理函数、普通工具函数里调用 Hook。
- 自定义 Hook 内部按条件提前 return,导致后续 Hook 有时不执行。