You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React 18中useEffect与useLayoutEffect差异解析及实操测试

关于React 18中useEffect与useLayoutEffect的疑问解答

一、第二段表述的具体含义

React 18对离散用户输入(比如点击按钮)触发的useEffect做了调用时机调整——让它在布局计算和页面绘制之前同步执行,但这个调整只影响回调函数本身的执行时机:

  • 如果你在useEffect回调里写了状态更新逻辑,这些更新不会立刻生效,React会把它们放进延迟队列,等当前的渲染周期完成后再处理;
  • 而useLayoutEffect不仅会在布局绘制前同步执行回调,回调里的状态更新会被立刻处理,不会延迟,相当于在同一渲染周期内完成更新和重新渲染。

二、文档中“updates”的指代

这里的updates就是指能触发React组件重新渲染的状态更新操作,比如:

  • 调用useState返回的更新函数(setCount(prev => prev +1)这类);
  • 调用useReducer的dispatch方法;
  • 其他能改变组件状态、引发重新渲染的操作。

三、实操测试区分两者

1. 日志打印看更新顺序

写一个简单组件,同时使用useEffect和useLayoutEffect,通过控制台日志看执行和更新顺序:

import { useState, useEffect, useLayoutEffect } from 'react';

function TestRenderOrder() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    console.log('👉 useEffect 回调执行');
    setCount(prev => prev + 1);
    console.log('useEffect 内当前count:', count);
  }, []);

  useLayoutEffect(() => {
    console.log('👉 useLayoutEffect 回调执行');
    setCount(prev => prev + 1);
    console.log('useLayoutEffect 内当前count:', count);
  }, []);

  console.log('🔄 组件渲染,当前count:', count);
  return <div>当前计数:{count}</div>;
}

控制台输出顺序:

🔄 组件渲染,当前count: 0
👉 useLayoutEffect 回调执行
useLayoutEffect 内当前count: 0
🔄 组件渲染,当前count: 1
👉 useEffect 回调执行
useEffect 内当前count: 1
🔄 组件渲染,当前count: 2

能明显看到:useLayoutEffect里的更新会立刻触发重新渲染,而useEffect的更新要等组件第一次渲染完成后才处理。

2. 视觉闪烁测试

通过修改DOM样式,直观感受两者的差异:

import { useState, useEffect, useLayoutEffect, useRef } from 'react';

function TestFlash() {
  const [isDark, setIsDark] = useState(false);
  const boxRef = useRef(null);

  // 先测试useEffect
  useEffect(() => {
    if (boxRef.current) {
      boxRef.current.style.backgroundColor = isDark ? '#000' : '#fff';
    }
  }, [isDark]);

  // 再换成useLayoutEffect测试
  // useLayoutEffect(() => {
  //   if (boxRef.current) {
  //     boxRef.current.style.backgroundColor = isDark ? '#000' : '#fff';
  //   }
  // }, [isDark]);

  return (
    <div>
      <button onClick={() => setIsDark(prev => !prev)}>切换主题</button>
      <div ref={boxRef} style={{ width: '200px', height: '200px', border: '1px solid #666' }}></div>
    </div>
  );
}
  • 用useEffect时,点击按钮后会先看到盒子保持原颜色,瞬间变成目标颜色,出现短暂闪烁;
  • 换成useLayoutEffect后,颜色切换在页面绘制前完成,不会有闪烁感。

内容的提问来源于stack exchange,提问作者Hardwork

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 08:31:13