前端面试题——React篇

文章目录


前言

准备了一些高频面试题,有需要的小伙伴可以收藏,需要的时候看看,也会持续更新。


1.useEffect是异步还是同步

useEffect的执行是异步的,这主要是为了确保它不会阻塞浏览器的绘制过程,从而保持用户界面的响应性。

为何是异步

1、避免阻塞浏览器绘制:

如果 useEffect 同步执行,那么在组件渲染过程中,所有的副作用逻辑(比如数据获取、DOM 操作、订阅等)都必须执行完毕,浏览器才能继续绘制。这会导致用户界面在副作用执行期间停顿,影响用户体验。

2、保持数据一致性:

React 的渲染过程是异步和批处理的。在渲染过程中,多个状态更新可能被批处理。如果 useEffect 是同步执行的,可能会导致在渲染过程中状态的不一致,因为副作用可能依赖于最新的渲染结果。异步执行 useEffect 确保了在所有 DOM 更新完成后再运行副作用逻辑,从而保证数据的一致性。

3、类比于生命周期:

在类组件中,副作用通常在 componentDidMountcomponentDidUpdate 生命周期方法中执行。React 将这些方法的执行也设计为异步,以便优化性能和用户体验。useEffect 是函数组件中的等价 Hook,因此也遵循相同的异步设计原则。

4、更好的性能优化:

React 可以通过异步执行副作用来更好地管理性能。比如,React 可以在必要时跳过不需要的副作用,或在空闲时间(通过 requestIdleCallback)执行一些较低优先级的副作用,从而提高应用的整体性能。

如何拿到最新的数据

1、使用useEffect依赖项:
useEffect 的第二个参数是一个数组,包含所有影响副作用执行的状态或变量。当这些依赖项发生变化时,useEffect 会重新执行。确保将数据作为依赖项传递给 useEffect,这样可以保证在数据更新后,副作用会重新执行,从而拿到最新的数据。

2、使用 async/await:

如果你在 useEffect 中使用了异步函数(比如 fetch),你可以使用 async/await 来确保在数据完全获取后再更新状态。

3、使用setTimeout:使用setTimeout时,将延迟时间设置为0或者省略,可拿到需要的最新数据。

  • 执行机制setTimeoutuseEffect在一起有多余的感觉,因为useEffect本身就是异步,而setTimeout也是异步的。即使没有 setTimeout,React 也会在组件渲染完成后立即执行,所以,setTimeout并不会改变其执行时机。
  • 性能考虑 :虽然将时间设置为 0 的 setTimeout 通常被用来将代码推迟到下一个事件循环中执行,但在这里,它只是增加了额外的无谓开销,没有提供任何实际的优势。这可能会对性能产生微小的负面影响。

2.微任务和宏任务

概念

1、微任务(microtask):
微任务是指在当前任务执行完毕后立即执行的任务。Promise回调函数、async/await(返回的也是一个promise)、process.nextTick、等都是微任务的例子。在React中,更新状态和执行副作用(如生命周期方法、钩子函数、effect hook等)通常被视为微任务。这意味着,当React组件的状态更新时,React会将相应的更新计划为微任务,以确保它们在当前任务执行结束后立即执行。

2、宏任务(macrotask):
宏任务是指需要在事件循环的下一个迭代中执行的任务。定时器(setTimeout、setInterval)、I/O 操作、UI 渲染等通常被视为宏任务。在React中,调度新的组件渲染、处理用户输入等也被认为是宏任务。

优点

在React中,通过将任务分解为微任务和宏任务,可以实现异步更新优化性能。例如,React可以利用微任务将多个状态更新合并成一个,从而减少渲染次数,提高性能。同时,宏任务的使用也确保了React能够在用户交互等事件之后及时更新UI,提供良好的用户体验。

3.事件循环(Event Loop)

概念

事件循环(Event Loop)是Javascript运行时环境的一部分,它负责管理代码的执行顺序,简单来说就是Javascript的一种运行机制,解决浏览器的单线程问题。

Javascript单线程任务从时间上分为同步任务和异步任务,而异步任务又分为宏任务(macrotask)和微任务(microtask)。

执行机制

  1. 执行全局同步代码,将其中的函数调用推入调用栈中。
  2. 当调用栈为空时,事件循环开始执行微任务队列中的任务,直到微任务队列为空。
  3. 从任务队列中取出一个任务,并将其推入调用栈中执行。
  4. 重复上述步骤,直到任务队列和微任务队列都为空。

4.React性能优化手段

  1. 避免不必要的渲染合理使用shouldComponentUpdateReact.PureComponent ,使用 shouldComponentUpdate 来控制组件是否需要重新渲染。React.PureComponent 自动实现了 shouldComponentUpdate,浅比较 props 和 state,函数组件可使用React.memo
  2. 使用合适的数据结构和状态管理 :使用不可变数据结构(如 Immutable.js)有助于高效地进行数据比较和变更检测;适当地提升状态,避免在层级过深的组件树中传递大量数据。使用 React.Context 来避免深层级的 props 传递。
  3. 避免匿名函数和对象:在渲染方法中避免定义匿名函数和对象,因为每次渲染都会生成新的引用,导致子组件的重新渲染。
  4. 代码分割和懒加载 :使用 React.lazyReact.Suspense 进行代码分割和组件懒加载,减少初始加载时间。
  5. 使用虚拟化列表 :对于长列表,使用虚拟化技术(如 react-windowreact-virtualized)来只渲染视口中的项目,避免渲染大量的 DOM 节点。
  6. 合理使用 useCallbackuseMemo :对于函数和复杂计算结果,使用 useCallbackuseMemo 来避免不必要的重新创建。
  7. 列表项使用 key 属性key 属性帮助 React 高效地进行 DOM diff 算法,从而减少不必要的 DOM 操作,当列表发生变化时,React 可以使用 key 来确定哪些元素需要更新、插入或删除。
  8. 使用生产模式:确保在生产环境中使用 React 的生产版本。开发版本包含额外的警告和检查,性能较低,生产版本会进行代码压缩和性能优化。
相关推荐
Myli_ing40 分钟前
HTML的自动定义倒计时,这个配色存一下
前端·javascript·html
dr李四维1 小时前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
雯0609~1 小时前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ1 小时前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z1 小时前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
彭世瑜2 小时前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4042 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish2 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five2 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序2 小时前
vue3 封装request请求
java·前端·typescript·vue