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

React组件函数在useEffect后重复执行及useLayoutEffect更新后useEffect仍执行的疑问

React组件渲染与生命周期钩子疑问

疑问点

  • 组件函数中的代码为何会在useEffect执行后再次运行?
  • 在useLayoutEffect中更新状态后,useEffect为何仍会执行?

示例代码

import { useEffect, useState, useLayoutEffect } from "react";
export default function App() {
  const [count, setCount] = useState(0);

  console.log("count in code: ", count);

  useEffect(() => {
    console.log("useEffect");
  }, [count]);

  useLayoutEffect(() => {
    console.log("count in uselayout: ", count);
    setCount(1);
  }, [count]);

  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

预期与实际日志

预期逻辑

首次渲染输出count in code: 0,接着执行useLayoutEffect和useEffect日志,随后useLayoutEffect的状态更新触发重渲染,再次输出count in code: 1、useLayoutEffect和useEffect日志。

实际输出

count in code:  0
count in uselayout:  0
useEffect (useLayoutEffect已更新状态,为何useEffect仍执行?不该被跳过吗?)
count in code:  1
count in uselayout:  1
useEffect
count in code:  1 (为何有这条额外日志?)

问题解答

1. 组件函数代码多次运行的原因

组件函数本身就是React的渲染入口,每次组件状态/ props变化时,React都会重新调用组件函数生成新的UI快照。你看到的额外count in code: 1,是开发环境下React严格模式(Strict Mode)的特性:严格模式会对组件函数、状态初始化、钩子回调进行重复调用,目的是检测潜在的副作用问题,生产环境不会出现该额外渲染。

2. useLayoutEffect更新状态后useEffect仍执行的原因

首次渲染的完整流程是:

  • 调用组件函数,输出count in code: 0
  • 执行useLayoutEffect(此时count为0),调用setCount(1)触发状态更新
  • React立即同步触发重渲染,组件函数再次执行,输出count in code:1,执行本次渲染的useLayoutEffect(count为1,不再触发状态更新)
  • 所有同步渲染完成后,React会执行之前已经调度好的首次渲染对应的useEffect(其依赖count=0已满足执行条件),之后再执行第二次渲染的useEffect(依赖count=1),因此会出现两次useEffect日志。

简单来说:首次渲染的useEffect已经进入调度队列,即使useLayoutEffect触发了重渲染,已经排队的useEffect仍会执行,不会被跳过。

关于额外的count in code:1日志

这是开发环境严格模式的重复渲染导致的。严格模式下,React会对每次有效渲染做一次额外的重复调用,因此第二次渲染(count=1)会被执行两次,产生两条count in code:1的日志,生产环境运行时该日志会消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:32:18