前端面试题:React 函数组件的性能优化方式

7 阅读1分钟

1. React.memo()

  • 作用:缓存函数组件,对 props 进行浅比较,避免重复渲染。

  • 用法

    jsx

    复制

    const MyComponent = React.memo(({ value }) => {
      return <div>{value}</div>;
    });
    
    // 自定义比较函数
    const areEqual = (prevProps, nextProps) => {
      return prevProps.value === nextProps.value;
    };
    React.memo(MyComponent, areEqual);
    

2. useCallback

  • 作用:缓存函数引用,避免子组件因函数引用变化而重新渲染。

  • 用法

    jsx

    复制

    const Parent = () => {
      const [count, setCount] = useState(0);
      const handleClick = useCallback(() => {
        setCount(c => c + 1);
      }, []); // 依赖数组为空,函数不会重新创建
    
      return <Child onClick={handleClick} />;
    };
    
    const Child = React.memo(({ onClick }) => {
      return <button onClick={onClick}>Click</button>;
    });
    

3. useMemo

  • 作用:缓存计算结果,避免重复计算。

  • 用法

    jsx

    复制

    const expensiveValue = useMemo(() => {
      return computeExpensiveValue(a, b);
    }, [a, b]); // 仅当 a 或 b 变化时重新计算
    

4. 优化 useEffect 依赖项

  • 问题:不合理的依赖项会导致副作用频繁执行。

  • 优化:精确声明依赖项,或使用 useRef 保存可变值。

    jsx

    复制

    useEffect(() => {
      const timer = setInterval(() => {
        console.log('Tick');
      }, 1000);
      return () => clearInterval(timer);
    }, []); // 空依赖表示只在挂载时执行
    

5. 避免滥用状态提升

  • 问题:将状态提升到过高层级的组件会导致不必要的渲染。
  • 优化:使用状态管理库(如 Redux、Recoil)或 useContext + useReducer 局部管理状态。

6. 使用 useRef 保存非响应式变量

  • 作用:保存与渲染无关的变量(如 DOM 引用、计时器 ID),避免触发重新渲染。

    jsx

    复制

    const intervalRef = useRef();
    useEffect(() => {
      intervalRef.current = setInterval(() => { /* ... */ }, 1000);
      return () => clearInterval(intervalRef.current);
    }, []);