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

React点击器游戏:如何解决useState状态显示跳变问题?

问题分析与修复方案

核心问题原因

  • 多个定时器同时运行:setInterval直接写在组件函数内部,每次组件渲染(状态变化时)都会创建新的定时器,多个定时器同时修改状态,导致数值跳变。
  • 闭包陷阱导致状态更新错误:直接使用findWorkCount + 1这种方式更新状态时,依赖的是当前渲染周期的旧状态值,当多个更新操作叠加时,会基于旧值重复计算,导致状态不符合预期。

修复后的代码

import { useState, useEffect } from 'react';

function App() {
  const [findWorkCount, setfindWorkCount] = useState(0);

  useEffect(() => {
    // 仅在组件挂载时创建一次定时器
    const timer = setInterval(() => {
      setfindWorkCount(prevCount => {
        // 基于最新状态计算新值,进度满100%后重置为0
        return prevCount >= 100 ? 0 : prevCount + 1;
      });
    }, 500);

    // 组件卸载时清理定时器,避免内存泄漏
    return () => clearInterval(timer);
  }, []); // 空依赖数组确保仅执行一次

  return (
    <div className="App">
      <button
        onClick={() => {
          // 按钮点击也用函数式更新,规避闭包问题
          setfindWorkCount(prevCount => {
            const newCount = prevCount + 11;
            return newCount >= 100 ? 0 : newCount;
          });
        }}
      >
        Find Job
      </button>
      <div className="bar">
        <div className="fillwork" style={{ width: `${findWorkCount}%` }}>
          <div className="counter">{findWorkCount}%</div>
        </div>
      </div>
    </div>
  );
}

export default App;

关键修改点说明

  • 用useEffect管理定时器生命周期:把定时器创建逻辑放到useEffect中,空依赖数组确保组件挂载仅执行一次;同时添加清理函数,在组件卸载时销毁定时器,避免多个定时器冲突和内存泄漏。
  • 函数式状态更新:调用setfindWorkCount时传入回调函数,每次都基于最新的状态值计算新值,彻底解决闭包导致的旧状态复用问题。
  • 统一状态重置逻辑:将自动增长和按钮点击的重置条件统一为>=100时归零,让进度条的行为保持一致,符合视觉预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 01:35:45