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

React 18中useState与useEffect重复执行问题求助

解决React中useEffect初始执行导致不必要输赢判定的问题

核心问题分析

你遇到的useEffect执行两次的情况,是React 18严格模式下的开发环境特性(生产环境只会执行一次),但核心痛点是页面初始加载时就触发了输赢判定——因为betMultiplier初始值为1,multiplier初始值为2,挂载时useEffect会直接执行判定逻辑。

最优解决方案:将判定逻辑直接整合到用户触发函数中

既然runMultiplier是用户主动操作(如下注按钮点击)才会调用的函数,完全不需要依赖useEffect监听状态更新做判定,直接在函数内部计算出新倍率后立即执行输赢判断即可,彻底避开初始挂载的问题:

const [betMultiplier, setBetMultiplier] = useState(1);

const runMultiplier = () => {
  let layer = Math.random();
  let i = 0;
  let newMultiplier;

  if (layer < 0.505) {
    newMultiplier = +(Math.random() * 1 + 1).toFixed(2);
  } else {
    while (layer > 0.5) {
      layer = Math.random();
      if (layer < 0.5) break;
      i++;
      if (i > 17) {
        newMultiplier = 1000000;
        break;
      }
    }
    // 增加边界判断,避免i超出multiplierRange数组长度导致报错
    if (!newMultiplier && multiplierRange[i]) {
      newMultiplier = +((Math.random() * (multiplierRange[i][1] - multiplierRange[i][0])) + multiplierRange[i][0]).toFixed(2);
    }
  }

  // 更新状态
  setBetMultiplier(newMultiplier);
  // 直接执行输赢判定
  if (multiplier >= newMultiplier) {
    console.log('you win!');
  } else {
    console.log('you lose!');
  }
};

// 移除原有的useEffect

备选方案:保留useEffect但区分初始挂载与用户触发更新

如果因业务需求必须保留useEffect,可以用useRef标记是否为用户主动触发的更新,而非初始挂载:

const [betMultiplier, setBetMultiplier] = useState(1);
const isUserTriggered = useRef(false);

const runMultiplier = () => {
  isUserTriggered.current = true;
  let layer = Math.random();
  let i = 0;

  if (layer < 0.505) {
    setBetMultiplier(+(Math.random()*1+1).toFixed(2));
  } else {
    while (layer > 0.5) {
      layer = Math.random();
      if (layer < 0.5) break;
      i++;
      if (i > 17) {
        setBetMultiplier(1000000);
        break;
      }
    }
    setBetMultiplier(+((Math.random()*(multiplierRange[i][1]-multiplierRange[i][0]))+multiplierRange[i][0]).toFixed(2));
  }
};

useEffect(() => {
  // 初始挂载时跳过判定
  if (!isUserTriggered.current) return;

  if (multiplier >= betMultiplier) {
    console.log('you win!');
  } else {
    console.log('you lose!');
  }
  // 重置标记,避免非用户触发的更新误执行
  isUserTriggered.current = false;
}, [betMultiplier, multiplier]);

注意事项

  1. React 18严格模式的两次执行仅存在于开发环境,用于检测组件副作用是否符合预期,生产环境不会出现该情况;
  2. 注意runMultiplier中i可能超出multiplierRange数组长度的情况,务必添加边界判断避免报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:40:19