准备了一些高频面试题,有需要的小伙伴可以收藏,需要的时候看看,也会持续更新。
useEffect的执行是异步的,这主要是为了确保它不会阻塞浏览器的绘制过程,从而保持用户界面的响应性。
1、避免阻塞浏览器绘制:
如果 useEffect
同步执行,那么在组件渲染过程中,所有的副作用逻辑(比如数据获取、DOM 操作、订阅等)都必须执行完毕,浏览器才能继续绘制。这会导致用户界面在副作用执行期间停顿,影响用户体验。
2、保持数据一致性:
React 的渲染过程是异步和批处理的。在渲染过程中,多个状态更新可能被批处理。如果 useEffect
是同步执行的,可能会导致在渲染过程中状态的不一致,因为副作用可能依赖于最新的渲染结果。异步执行 useEffect
确保了在所有 DOM 更新完成后再运行副作用逻辑,从而保证数据的一致性。
3、类比于生命周期:
在类组件中,副作用通常在 componentDidMount
和 componentDidUpdate
生命周期方法中执行。React 将这些方法的执行也设计为异步,以便优化性能和用户体验。useEffect
是函数组件中的等价 Hook,因此也遵循相同的异步设计原则。
4、更好的性能优化:
React 可以通过异步执行副作用来更好地管理性能。比如,React 可以在必要时跳过不需要的副作用,或在空闲时间(通过 requestIdleCallback
)执行一些较低优先级的副作用,从而提高应用的整体性能。
1、使用useEffect依赖项:
useEffect
的第二个参数是一个数组,包含所有影响副作用执行的状态或变量。当这些依赖项发生变化时,useEffect
会重新执行。确保将数据作为依赖项传递给 useEffect
,这样可以保证在数据更新后,副作用会重新执行,从而拿到最新的数据。
2、使用 async/await:
如果你在 useEffect
中使用了异步函数(比如 fetch
),你可以使用 async/await 来确保在数据完全获取后再更新状态。
3、使用setTimeout:使用setTimeout
时,将延迟时间设置为0或者省略,可拿到需要的最新数据。
setTimeout
和useEffect
在一起有多余的感觉,因为useEffect
本身就是异步,而setTimeout
也是异步的。即使没有 setTimeout
,React 也会在组件渲染完成后立即执行,所以,setTimeout
并不会改变其执行时机。setTimeout
通常被用来将代码推迟到下一个事件循环中执行,但在这里,它只是增加了额外的无谓开销,没有提供任何实际的优势。这可能会对性能产生微小的负面影响。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,提供良好的用户体验。
事件循环(Event Loop)是Javascript运行时环境的一部分,它负责管理代码的执行顺序,简单来说就是Javascript的一种运行机制,解决浏览器的单线程问题。
Javascript单线程任务从时间上分为同步任务和异步任务,而异步任务又分为宏任务(macrotask)和微任务(microtask)。
shouldComponentUpdate
和 React.PureComponent
,使用 shouldComponentUpdate
来控制组件是否需要重新渲染。React.PureComponent
自动实现了 shouldComponentUpdate
,浅比较 props 和 state,函数组件可使用React.memo
。Immutable.js
)有助于高效地进行数据比较和变更检测;适当地提升状态,避免在层级过深的组件树中传递大量数据。使用 React.Context
来避免深层级的 props 传递。React.lazy
和 React.Suspense
进行代码分割和组件懒加载,减少初始加载时间。react-window
或 react-virtualized
)来只渲染视口中的项目,避免渲染大量的 DOM 节点。useCallback
和 useMemo
:对于函数和复杂计算结果,使用 useCallback
和 useMemo
来避免不必要的重新创建。key
属性帮助 React 高效地进行 DOM diff 算法,从而减少不必要的 DOM 操作,当列表发生变化时,React 可以使用 key
来确定哪些元素需要更新、插入或删除。