React:使用useEffect根据状态值修改div颜色时计数器到99后div消失
React加载计数器异常问题解决
问题场景
我有一个内部包含计数器的div,渲染代码如下:
return ( <div className="loading-div" style={styles} > <h1>Loading {count} %</h1> </div> );
计数器通过useEffect钩子中的setTimeout每0.1秒更新一次,代码如下:
useEffect((e) => { setTimeout(() => { count === 100 ? e.preventDefault() : setCount(() => count + 1); count === 35 ? setFont(() => font + 6) : setCount(() => count + 1); count === 70 ? setWidth(() => width + 100) : setCount(() => count + 1); count === 70 ? setHeight(() => height + 100) : setCount(() => count + 1); count === 99 ? setColor(() => color="lime") : setCount(() => count + 1); }, 100); })
运行到计数器到达99时,div消失了。猜测fontSize、width/height的修改生效是因为用了font + 5的方式,但setColor函数不生效是因为赋值后状态未立即改变?如何让计数器到达99时状态立即改变?
问题分析
- useEffect无依赖项+多次setCount:每次组件渲染都会创建新的
setTimeout,且每个条件分支都会调用setCount,导致count被快速累加,逻辑混乱。 - setColor写法错误:
setColor(() => color="lime")是错误的状态更新写法,函数式更新需要返回新值而非执行赋值语句,直接使用setColor("lime")即可。 - e.preventDefault()报错:
useEffect的回调参数不是事件对象,e为undefined,调用该方法会抛出错误,这就是div消失的直接原因。 - 状态更新异步特性:React状态更新是异步的,不能依赖当前
count值同步判断后续操作,需用函数式更新获取最新状态。
修正后的代码方案
import { useState, useEffect } from 'react'; function LoadingComponent() { const [count, setCount] = useState(0); const [font, setFont] = useState(16); const [width, setWidth] = useState(200); const [height, setHeight] = useState(100); const [color, setColor] = useState("gray"); useEffect(() => { if (count >= 100) return; const timer = setTimeout(() => { setCount(prevCount => { const newCount = prevCount + 1; if (newCount === 36) { setFont(prevFont => prevFont + 6); } if (newCount === 71) { setWidth(prevWidth => prevWidth + 100); setHeight(prevHeight => prevHeight + 100); } if (newCount === 100) { setColor("lime"); } return newCount; }); }, 100); return () => clearTimeout(timer); }, [count]); const styles = { width: `${width}px`, height: `${height}px`, fontSize: `${font}px`, color: color, border: "1px solid #ccc", display: "flex", alignItems: "center", justifyContent: "center" }; return ( <div className="loading-div" style={styles} > <h1>Loading {count} %</h1> </div> ); } export default LoadingComponent;
关键修正点
- 添加useEffect依赖项:将
count作为依赖,确保每次count更新后才创建新定时器,避免无限循环。 - 合并count更新逻辑:在
setCount的函数式更新中统一处理所有状态变化,确保基于最新count值判断。 - 修正setColor写法:直接传递新值
"lime",保证状态更新生效。 - 清除定时器:在useEffect清理函数中清除定时器,防止内存泄漏。
- 移除错误的preventDefault调用:通过
count >=100判断停止定时器,避免报错。
内容的提问来源于stack exchange,提问作者atanasovlj
相关产品推荐
相关产品推荐

