Hooks 为什么通常不能放进条件或循环?
先理解原理和示例,再练习完整口述与追问。
回答要点
React 依赖稳定调用顺序关联多数 Hook 的状态,应在函数组件或自定义 Hook 的顶层调用。把条件放在 Hook 内部的合适位置。React 的 use API 有特殊规则,不能机械套用所有 Hook 的限制。
原理拆解
普通 Hooks 的调用顺序是 React 对应每个组件内部状态槽位的重要依据。条件中少调用一次,会让后面的 Hook 对应到错误位置,因此 useState、useEffect 等应在组件或自定义 Hook 顶层稳定调用。条件属于副作用内容时,把条件放到 Effect 内部;条件属于组件树时,拆成有独立生命周期的子组件。
示例与推演
useEffect(() => {
if (!enabled) return
const connection = connect(roomId)
return () => connection.close()
}, [enabled, roomId])
Hook 每次都调用,但只有 enabled 时建立连接。React 新的 use API 存在特定例外,不能由此推导所有 Hook 都可随意进循环。
易错点
函数名以 use 开头不是获得合法性的魔法,仍需遵守执行位置与规则。不要为躲 lint 把 Hook 藏到一个普通工具函数里。
参考回答可直接练习口述
大多数 Hook 的状态与调用顺序关联,不能因为本次条件不同就少调用一个,否则后续 Hook 会对应到错误位置。因此 useState、useEffect 等应放在函数组件或自定义 Hook 顶层、提前返回之前。需要条件时,在 Effect 内判断或拆成独立组件。React 的 use API 支持部分条件和循环调用,是单独规定的例外。
面试官可能继续问追问与完整解答展开收起
追问
提前 return 前后调用 Hook 为什么会报错?普通函数里调用 useState 合法吗?React 官方 Hooks 规则
追问回答
某次提前 return 跳过 Hook,下一次却执行,会改变顺序并触发错误。普通工具函数不能随意调用 useState,它必须在 React 渲染函数组件或自定义 Hook 的合法上下文中执行;仅改函数名并不能让任意调用位置合法。