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

React中useEffect多次执行导致randomImgNum重复打印的原因及解决方法

问题原因分析

1. console.log多次打印的本质是组件重复渲染

你把console.log(randomImgNum)写在了组件函数顶层,每次调用setRandomImgNum或setRandomTxtNum更新状态时,都会触发组件重新渲染,这个console.log会跟着执行多次,看起来像是useEffect在重复执行,但其实是组件本身在反复渲染。

2. useEffect多次执行的直接原因

  • React 18严格模式的调试机制:开发环境下,React 18的严格模式会自动执行两次useEffect(以及其他副作用钩子),用来检测是否存在重复执行会引发问题的副作用,这是开发环境的特殊调试行为,生产环境不会出现。
  • 依赖项冗余+逻辑缺陷:你把setRandomImgNum和setRandomTxtNum放进了依赖数组,但这两个是useState返回的稳定函数,不会随渲染变化;更关键的是,调用setRandomImgNum后立刻用当前randomImgNum判断逻辑,此时randomImgNum还是更新前的旧值,逻辑不符合预期,同时状态更新又触发组件渲染,进一步增加了打印次数。
解决方案

1. 让useEffect仅执行一次的核心操作

将useEffect的依赖数组改为空数组[],这样useEffect只会在组件首次挂载时执行一次。

2. 修正内部逻辑(解决旧状态值问题)

setRandomImgNum是异步操作,调用后randomImgNum不会立刻更新,所以不能直接用当前状态值计算randomTxtNum,应该先算出随机图片编号,再根据这个值直接设置文本编号:

修正后的完整代码:

import React, { useEffect, useState } from "react";

export default function Load() {
  const [randomImgNum, setRandomImgNum] = useState<number>(1);
  const [randomTxtNum, setRandomTxtNum] = useState<number>(1); 

  useEffect(() => {
        // 先计算随机图片编号
        const imgNum = Math.floor(Math.random() * 3) + 1;
        setRandomImgNum(imgNum);
        
        const randNum = Math.floor(Math.random() * 100);
        // 用刚计算的imgNum设置文本编号,而非依赖状态旧值
        if (imgNum === 1) {
            setRandomTxtNum(randNum % 6 + 1);
        } else if (imgNum === 2) {
            setRandomTxtNum(randNum % 9 + 1);
        } else if (imgNum === 3) {
            setRandomTxtNum(randNum % 5 + 1);
        }
  }, []); // 空依赖数组,仅挂载时执行一次

  console.log(randomImgNum); // 现在仅在组件挂载和首次状态更新时打印(开发环境严格模式下可能打印两次,生产环境一次)
 
  return (
   <>
   </>
 );
}

额外说明

开发环境下若仍看到useEffect执行两次,属于React 18严格模式的正常调试行为,打包到生产环境后会自动消失,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 15:55:25