useLayoutEffect测量DOM尺寸是否可靠?对其执行时机的疑惑
关于useLayoutEffect的误解澄清与解答
首先纠正你对useLayoutEffect执行时机的核心误解:它的setup函数并不是在DOM节点加入前运行,而是在React把虚拟DOM的变更提交到真实DOM(包括首次挂载节点)之后、浏览器执行重绘操作之前同步执行的。
为什么能在重绘前测量尺寸?
React的渲染流程是这样的:
- 第一步:计算虚拟DOM的变更(比如首次渲染生成完整虚拟DOM)
- 第二步:把这些变更同步到真实DOM(此时节点已经挂载到DOM树里了,但浏览器还没来得及把它画到屏幕上)
- 第三步:同步执行所有useLayoutEffect的回调函数
- 第四步:浏览器执行重绘,把更新后的DOM渲染到屏幕上
所以你在useLayoutEffect里测量的是已经挂载到DOM的节点尺寸,只是这时候用户还看不到,因为浏览器还没完成重绘。
如何避免节点在测量时被用户看到?
如果不想让用户看到未准备好的节点,有两种常见方案:
- 初始给节点设置隐藏样式:比如
visibility: hidden(保留布局空间)或者position: absolute; left: -9999px(脱离正常布局流),等在useLayoutEffect里完成测量和调整后,再把样式改成可见。 - 利用useLayoutEffect的同步执行特性:即使节点初始是可见的,因为useLayoutEffect在重绘前就完成了样式调整,用户不会感知到中间状态的闪烁。
并发模式下的情况
你提到的并发模式中,React确实会有未提交到DOM的中间渲染状态,但这些状态不会触发useLayoutEffect——只有当React最终把渲染结果提交到DOM时,才会执行对应的useLayoutEffect回调。所以你在useLayoutEffect里拿到的始终是已经提交到DOM的真实节点,不用担心测量到无效的中间状态。
内容的提问来源于stack exchange,提问作者Guichi
相关产品推荐
相关产品推荐

