面试题答案
一键面试执行时机区别
- useEffect:
- 在浏览器完成布局与绘制之后,在一个延迟的事件循环中异步执行。这意味着它不会阻塞浏览器渲染,不会影响用户体验的流畅性。例如,如果在
useEffect
中进行网络请求等操作,页面会先渲染完成,然后再执行useEffect
中的代码。
- 在浏览器完成布局与绘制之后,在一个延迟的事件循环中异步执行。这意味着它不会阻塞浏览器渲染,不会影响用户体验的流畅性。例如,如果在
- useLayoutEffect:
- 其执行时机与
componentDidMount
、componentDidUpdate
非常类似,在浏览器完成布局与绘制之前,同步执行。这就有可能会阻塞浏览器渲染,如果在useLayoutEffect
中执行大量计算,用户可能会感觉到页面卡顿。
- 其执行时机与
使用场景区别
- useEffect:
- 网络请求:当需要从服务器获取数据时,由于网络请求本身是异步的,不会阻塞渲染,使用
useEffect
非常合适。例如,在一个博客文章列表页面,组件挂载后通过useEffect
发送请求获取文章数据。 - 订阅与事件监听:像订阅浏览器窗口大小变化事件
window.addEventListener('resize', callback)
,使用useEffect
来添加和清理这些监听器。因为这些操作不需要在渲染前完成,异步执行不会影响页面的初始渲染。
- 网络请求:当需要从服务器获取数据时,由于网络请求本身是异步的,不会阻塞渲染,使用
- useLayoutEffect:
- 操作DOM样式改变:如果需要根据DOM元素的布局来更新DOM样式,并且这个样式更新需要在用户看到页面之前完成,就适合用
useLayoutEffect
。例如,根据元素的宽度动态调整其字体大小,且要确保用户看到页面时字体大小已经调整好。 - 读取DOM布局信息:当需要在渲染后立即读取DOM布局信息并基于此进行操作时,
useLayoutEffect
是更好的选择。比如获取一个元素的高度并据此调整其他元素的位置。
- 操作DOM样式改变:如果需要根据DOM元素的布局来更新DOM样式,并且这个样式更新需要在用户看到页面之前完成,就适合用
选择useLayoutEffect而非useEffect的情况
- 样式闪烁问题:
- 当对DOM的样式修改会引起视觉上的闪烁(例如,根据窗口大小改变元素的位置,如果先渲染旧位置,再更新到新位置,可能会看到闪烁),使用
useLayoutEffect
可以在渲染前完成样式调整,避免闪烁。
- 当对DOM的样式修改会引起视觉上的闪烁(例如,根据窗口大小改变元素的位置,如果先渲染旧位置,再更新到新位置,可能会看到闪烁),使用
- 依赖DOM布局的即时计算:
- 如果计算逻辑依赖于最新的DOM布局信息,并且需要在渲染前完成计算。例如,要实现一个根据文本长度自动换行并调整容器高度的功能,需要在渲染前获取文本长度和容器宽度等DOM布局信息来计算高度,此时
useLayoutEffect
能保证在渲染前获取准确的布局信息并完成计算。
- 如果计算逻辑依赖于最新的DOM布局信息,并且需要在渲染前完成计算。例如,要实现一个根据文本长度自动换行并调整容器高度的功能,需要在渲染前获取文本长度和容器宽度等DOM布局信息来计算高度,此时