useLayoutEffect和useEffect区别详解

useLayoutEffect和useEffect区别详解

useLayoutEffectuseEffect 是 React 中用于处理副作用的两个钩子,它们的核心区别在于 执行时机对渲染流程的影响。以下是详细对比:

1. 执行时机对比

useLayoutEffectuseEffect
触发时机在 DOM 更新后、浏览器绘制前 同步执行在 DOM 更新后、浏览器绘制后 异步执行
执行顺序先执行后执行
代码示例useLayoutEffect(() => {// 同步立即执行})useEffect(() => {// 异步延迟执行})

2. 对渲染的影响

useLayoutEffectuseEffect
是否阻塞渲染✅ 会阻塞浏览器绘制❌ 不阻塞渲染
适用场景需要同步读取/修改 DOM 布局的场景数据获取、事件监听等非紧急操作
风险提示过度使用会导致页面卡顿无显著性能风险

3. 典型使用场景

适合用 useLayoutEffect 的情况:
  1. 读取或修改 DOM 尺寸/布局

    useLayoutEffect(() => {
      const width = divRef.current.offsetWidth;
      setWidth(width); // 同步更新避免闪烁
    }, []);
    
  2. 同步状态到 DOM

    useLayoutEffect(() => {
      inputRef.current.value = state; // 立即更新输入框值
    }, [state]);
    
  3. 动画起始状态设置

    useLayoutEffect(() => {
      element.style.transform = 'scale(1)'; // 避免初始闪烁
    }, []);
    
适合用 useEffect 的情况:
  1. 数据获取

    useEffect(() => {
      fetchData().then(setData);
    }, []);
    
  2. 事件监听

    useEffect(() => {
      window.addEventListener('resize', handleResize);
      return () => window.removeEventListener('resize', handleResize);
    }, []);
    
  3. 非紧急副作用

    useEffect(() => {
      analytics.log('Component mounted');
    }, []);
    

4. 执行流程问题图解

在这里插入图片描述

sequenceDiagram
    React->>DOM: 更新虚拟DOM
    React->>DOM: 应用变更到真实DOM
    rect rgb(200, 150, 255)
    Note right of React: useLayoutEffect
    React->>useLayoutEffect: 同步执行
    end
    Browser->>Paint: 浏览器绘制页面
    rect rgb(150, 255, 150)
    Note right of Browser: useEffect
    Browser->>useEffect: 异步执行
    end

5. 性能注意事项

  1. useLayoutEffect 的风险
    • 长时间运行的逻辑会阻塞页面渲染
    • 在服务端渲染 (SSR) 中会导致警告(需替换为 useEffect
  2. 黄金法则
    • 默认先用 useEffect
    • 只有遇到视觉闪烁/布局问题时才用 useLayoutEffect

6. 代码示例:避免闪烁

function Tooltip() {
  const [position, setPosition] = useState({ top: 0, left: 0 });
  const ref = useRef();

  // 用 useLayoutEffect 避免位置闪烁
  useLayoutEffect(() => {
    const { height } = ref.current.getBoundingClientRect();
    setPosition({ top: height + 10, left: 0 });
  }, []);

  return (
    <div ref={ref} style={{ position: 'absolute', ...position }}>
      Tooltip
    </div>
  );
}

7. 总结选择标准

问题类型应选钩子
“我需要读取/修改 DOM 布局”useLayoutEffect
“我要获取数据或添加事件”useEffect
“用户会看到中间状态闪烁”useLayoutEffect
“副作用不紧急”useEffect
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值