如何使用setInterval每秒递增React state?适配短间隔场景
问题根因
你当前代码的核心问题是将setInterval放在了组件根作用域下,每次组件因为count状态更新触发重渲染时,都会创建一个全新的定时器实例。随着定时器不断累积,多个定时器回调执行次数失控,就会出现计数随机增长、无法停止的问题。
正确实现方案
基础稳定版
适配所有时间间隔场景,包括100ms、10ms等短间隔都可直接使用:
import { useState, useEffect, useRef } from 'react'; export default function App() { const [count, setCount] = useState(0); // 用useRef存储定时器ID,避免重渲染时丢失引用 const timerIdRef = useRef(null); // 可自定义修改时间间隔,支持10ms/100ms/1000ms均可 const COUNT_INTERVAL = 10; useEffect(() => { // 仅在组件挂载时创建一次定时器 timerIdRef.current = setInterval(() => { // 使用函数式更新保证拿到最新的count值 setCount(oldCount => oldCount + 1); }, COUNT_INTERVAL); // 组件卸载时自动清理定时器,避免内存泄漏 return () => clearInterval(timerIdRef.current); }, []); // 空依赖数组保证useEffect只会在挂载和卸载时执行 return <div>{count}</div>; }
高精度优化版(适配超短间隔场景)
如果使用10ms这类超短间隔且对计时精度要求高,可加入时间差校准逻辑,避免主线程阻塞、定时器回调延迟导致的累计误差:
import { useState, useEffect, useRef } from 'react'; export default function App() { const [count, setCount] = useState(0); const timerIdRef = useRef(null); // 存储上一次触发的基准时间 const lastTriggerTimeRef = useRef(performance.now()); const COUNT_INTERVAL = 10; useEffect(() => { timerIdRef.current = setInterval(() => { const currentTime = performance.now(); const timeDiff = currentTime - lastTriggerTimeRef.current; // 计算当前应该递增的步数,补回阻塞漏加的计数 const addStep = Math.floor(timeDiff / COUNT_INTERVAL); if (addStep >= 1) { setCount(oldCount => oldCount + addStep); // 校准下一次触发的基准时间,消除余数误差 lastTriggerTimeRef.current = currentTime - (timeDiff % COUNT_INTERVAL); } }, COUNT_INTERVAL); return () => clearInterval(timerIdRef.current); }, []); return <div>{count}</div>; }
使用注意事项
- 短间隔场景下不要在定时器回调中执行大量计算操作,避免阻塞主线程导致计数偏差
- 如果需要暂停/重启计数,可在useEffect的依赖数组中加入控制状态,对应更新即可
内容的提问来源于stack exchange,提问作者Saarthak
相关产品推荐
相关产品推荐

