React Hooks中为何能调用后方声明的函数表达式?
原理解释
这个运行逻辑和React的特殊黑魔法无关,本质是JavaScript闭包特性+React useEffect的执行时序共同作用的结果,逐行拆解你给出的示例代码执行流程就能完全搞懂:
const Component = () => { useEffect(()=>{func()}, []) const func = () => console.log("Why?") return <></> }
组件首次渲染时的执行顺序是:
- 组件函数启动同步执行,走到
useEffect调用行时,React只会把你传入的回调函数()=>{func()}暂存到当前组件的待执行effect队列里,不会在这个同步阶段执行回调内部的代码,所以这时候根本不会触发func()的调用,自然不会出现找不到变量的错误。 - 代码继续向下执行,走到
const func = () => console.log("Why?")行,在当前组件函数的作用域内完成func常量的初始化,赋值为对应的箭头函数。 - 代码走到return语句,返回JSX结构,React完成DOM的渲染提交流程。
- DOM提交完成后,React开始处理待执行的effect队列:因为这个effect的依赖是空数组,只会在首次挂载后执行一次,此时调用之前暂存的回调,回调内部访问
func时,当前组件作用域内的func早就完成了初始化,配合JS的闭包特性,回调可以正常拿到func的引用执行,最终打印出Why?。
注意:如果把代码改成在useEffect传参的同步阶段就直接调用func,会立刻触发
const声明的暂时性死区报错:const Component = () => { // 传参时就同步执行func(),此时func还未初始化,直接抛错 useEffect(func(), []) const func = () => console.log("Why?") return <></> }报错内容为
Cannot access 'func' before initialization,这也能侧面印证:只要不是同步立刻执行回调内部的代码,就不会碰到变量未初始化的问题。
内容的提问来源于stack exchange,提问作者Dzianis Czaplia
相关产品推荐
相关产品推荐

