组件挂载时注册的事件处理器无法获取最新props值的原因
问题解答
你的猜想完全正确,下面是这个行为背后的具体原因:
函数组件的渲染与闭包捕获
React函数组件每次接收到新的props(或state变化)时,会重新执行整个组件函数,生成全新的props对象和组件内部的所有函数(包括displayCount)。
你的第一个useEffect依赖项是空数组[],这意味着它只会在组件第一次挂载时执行一次:
- 此时绑定的
displayCount是第一次渲染时创建的函数,它通过闭包捕获了当时的props对象(也就是初始的count值)。 - 后续父组件传递新的
count时,组件会重新渲染,生成新的props和新的displayCount函数,但旧的displayCount已经被绑定到window.focus事件上,且没有被替换——因为第一个useEffect不会再执行,所以事件触发时,始终是旧的displayCount在执行,它引用的还是第一次渲染时的props,自然只能打印初始值。
为什么Ref能解决问题
useRef创建的对象是一个可变的容器,它的current属性不会被React的渲染机制捕获:
- 每次
count更新时,第二个useEffect会触发,把最新的count赋值给countRef.current。 displayCount访问countRef.current时,直接读取的是这个容器的最新值,不受闭包捕获的旧值影响,所以能打印出最新的count。
补充:另一种解决方案
除了用Ref,你也可以让第一个useEffect监听count的变化,每次count更新时重新绑定事件:
useEffect(() => { const displayCount = () => { console.log("count prop -> " + props.count); }; window.addEventListener('focus', displayCount); return () => { window.removeEventListener('focus', displayCount); }; }, [count]); // 依赖count,每次count变化重新执行
这种方式每次count更新时,都会创建新的displayCount函数并重新绑定,确保事件触发时引用的是最新的props。
内容的提问来源于stack exchange,提问作者RDX
相关产品推荐
相关产品推荐

