MST

星途 面试题库

面试题:React Hooks性能优化与原理

在React应用中使用Hooks时,如何避免不必要的渲染以优化性能?结合useEffect和useMemo,说明它们的依赖数组的工作原理,以及在复杂场景下如何正确设置依赖以确保性能最佳。同时,请解释为什么在某些情况下useEffect会触发多次?
29.7万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

避免不必要渲染优化性能

  1. useMemo:用于缓存值,只有当依赖数组中的值发生变化时才重新计算。例如:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

这样,只要 ab 不变,computeExpensiveValue 就不会重新执行,避免了不必要的计算,也就减少了可能导致的不必要渲染。 2. useEffect:可以控制副作用的执行时机。通过正确设置依赖数组,只有依赖数组中的值发生变化时,副作用才会重新执行。例如:

useEffect(() => {
  // 副作用代码
  document.title = `You clicked ${count} times`;
}, [count]);

只有 count 变化时,才会更新 document.title,避免了在其他无关状态变化时触发不必要的副作用执行,进而避免不必要渲染。

useEffect和useMemo依赖数组工作原理

  1. useEffect:依赖数组决定了副作用何时重新运行。当组件渲染时,useEffect 会执行一次。后续每次渲染,如果依赖数组中的值有任何一个发生变化,useEffect 就会再次执行副作用函数。如果依赖数组为空 [],则 useEffect 只会在组件挂载和卸载时执行,因为没有任何状态变化会触发它再次运行。
  2. useMemo:依赖数组决定了缓存值何时重新计算。只有依赖数组中的值发生变化时,useMemo 才会重新执行传入的函数并返回新的缓存值。如果依赖数组为空 [],则 useMemo 在组件挂载时计算一次值,之后不会再重新计算,始终返回第一次计算的值。

复杂场景下正确设置依赖

  1. 确定真正依赖:仔细分析副作用或计算逻辑中使用到的所有外部变量,将它们全部放入依赖数组。如果遗漏依赖,可能导致副作用使用到过期的数据,或者 useMemo 没有在相关数据变化时重新计算。
  2. 拆分副作用:对于复杂的副作用,可以拆分成多个 useEffect,每个 useEffect 专注于处理不同的依赖关系,使依赖数组更清晰,避免因为将所有依赖放在一起而导致不必要的频繁触发。

useEffect触发多次的原因

  1. 初始渲染和更新:在组件挂载(初始渲染)时,useEffect 会执行一次。之后,只要依赖数组中的值发生变化,useEffect 就会再次执行,所以看起来像是触发了多次。
  2. 函数式更新:如果在 useEffect 内部使用函数式更新(如 setState(prevState => ({...prevState, newData: 'value' }))),并且没有正确设置依赖,可能导致多次触发。因为函数式更新会创建新的函数引用,而如果依赖数组中没有包含这些函数,useEffect 就会因为捕获到不同的函数引用而多次触发。
  3. 嵌套组件和父组件更新:如果 useEffect 所在组件是嵌套在其他组件中的,父组件的更新可能会导致子组件重新渲染,进而可能触发子组件中的 useEffect。如果父组件频繁更新且子组件的 useEffect 依赖数组设置不当,就会出现多次触发的情况。