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

React useState使用疑问:定时器中更新count状态始终为0原因求解

问题原因

  • 核心是React函数组件闭包陷阱:触发chrono函数时,当前渲染周期闭包里的count为初始值0,setInterval的回调函数会永久持有该闭包的引用,后续每次执行回调读取的都是被捕获的旧值0,和更新后的state无关。
  • 隐藏问题:未存储定时器ID,多次点击会生成多个并行定时器导致计数异常,组件卸载时也无法清理定时器会造成内存泄漏。

修复方案

做两处核心调整即可:

  1. setCount改用函数式更新写法,入参可以直接拿到最新的state值,不受闭包旧值影响
  2. 用useRef存储定时器ID,实现定时器启停控制和卸载清理

修改后完整App组件代码

import { Button } from './components/Button';
import { useState, useEffect, useRef } from 'react';

function App() {
  const [count, setCount] = useState(0);
  // 用ref存储定时器ID,跨渲染周期保持引用不变
  const timerRef = useRef(null);
  
  const chrono = () => {
    // 启动前清理已有定时器,避免多个并行运行
    if (timerRef.current) clearInterval(timerRef.current);
    timerRef.current = setInterval(() => {
      // 函数式更新,每次读取最新的count值
      setCount(prevCount => prevCount + 1);
    }, 1000);
  }

  // 组件卸载时清理定时器,避免内存泄漏
  useEffect(() => {
    return () => {
      if (timerRef.current) clearInterval(timerRef.current);
    }
  }, [])

  // 若需要打印最新的count值,单独用useEffect监听count变化即可
  useEffect(() => {
    console.log(count);
  }, [count])

  return (
    <>
      <Button clicAction={chrono} nom="Start the timer"/>
      <p>{count}</p>
    </>
  );
}

export default App;

小提示:你的Button组件里导入的useState没有被使用,可以直接删掉,不会影响现有功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 11:45:04