React中正确使用setInterval的方法及React18下计数每次加2的原因
React中setInterval的正确用法与React 18计数翻倍问题解析
一、如何在React中正确使用setInterval?
React的渲染机制和闭包特性,要求使用setInterval时注意以下几点:
- 必须配合清理函数:组件卸载或副作用重新执行时,一定要清除定时器,避免内存泄漏和无效定时器持续运行。
基础示例:import { useState, useEffect } from 'react'; function Timer() { const [count, setCount] = useState(0); useEffect(() => { const intervalId = setInterval(() => { // 用函数式更新获取最新状态,避开闭包陷阱 setCount(prevCount => prevCount + 1); }, 1000); // 组件卸载时清除定时器 return () => clearInterval(intervalId); }, []); return <div>当前计数:{count}</div>; } - 优先使用函数式更新状态:如果定时器回调里要更新状态,别直接用
setCount(count + 1),这种写法会捕获渲染时的旧count值,导致状态更新滞后。用setCount(prev => prev + 1)能确保每次拿到最新的状态值。 - 处理动态依赖:如果定时器的逻辑依赖props或其他state,一定要把这些依赖项加入useEffect的依赖数组。比如动态调整间隔时间:
useEffect(() => { const intervalId = setInterval(() => { setCount(prev => prev + 1); }, updateInterval); return () => clearInterval(intervalId); }, [updateInterval]); // 依赖变化时重新创建定时器
二、React 18中count每次增加2的原因
这是React 18开发环境下Strict Mode的特性导致的:Strict Mode会自动执行两次组件挂载逻辑(包括useEffect的回调),用来检测未清理的副作用、重复挂载的bug等。
你提供的代码里,useEffect的空依赖数组会让它在组件挂载时执行,但因为没有清理函数,第一次执行创建的定时器没被清除,第二次执行又创建了一个新的定时器。两个定时器每秒都会调用setCount(prev => prev +1),所以count每秒会增加2。
修复方法
给useEffect加上清理函数,每次重新执行useEffect(包括Strict Mode的二次挂载)时,先清除旧定时器:
const [count, setCount] = useState(0) useEffect(() => { const intervalId = setInterval(() => { setCount(count => count + 1) }, 1000) // 清理函数:在组件卸载或useEffect重新执行前清除定时器 return () => clearInterval(intervalId) }, []) return ( <div>{count}</div> )
加上清理函数后,Strict Mode第二次执行useEffect时,会先清除第一次创建的定时器,最终只会保留一个正常工作的定时器,count就会每秒增加1了。另外要注意,这个问题只在开发环境出现,生产环境下Strict Mode不会触发二次挂载,但加上清理函数是必须的编码规范,能避免内存泄漏。
内容的提问来源于stack exchange,提问作者simba
相关产品推荐
相关产品推荐

