React中setTimeout未按预期工作:方块逐次动画失效问题
问题分析与解决方案
你遇到的问题核心是所有setTimeout的延迟时间都设成了500ms,循环执行时会一次性把6个定时器都注册,它们会在同一时间点触发回调,自然所有方块会同时显示。
修复代码
把每个定时器的延迟时间改成500 * i,让每个方块的动画依次延迟触发:
import { useState, useRef, useEffect } from 'react'; function SquareAnimation() { let [scale, setScale] = useState({ prop1: 'scale(0)', prop2: 'scale(0)', prop3: 'scale(0)', prop4: 'scale(0)', prop5: 'scale(0)', prop6: 'scale(0)' }) // 用useRef保存定时器ID,防止多次点击叠加动画 const timersRef = useRef([]); const animate = () => { // 先清除之前的定时器,避免重复点击导致混乱 timersRef.current.forEach(timer => clearTimeout(timer)); timersRef.current = []; for (let i = 1; i <= 6; i++){ const timer = setTimeout(() => { const key = `prop${i}`; setScale(prev => ({...prev, [key]: 'scale(1)'})); }, 500 * i); // 这里改成递增的延迟时间 timersRef.current.push(timer); } } // 组件卸载时清除定时器,防止内存泄漏 useEffect(() => { return () => { timersRef.current.forEach(timer => clearTimeout(timer)); }; }, []); return ( <div> <button onClick={animate}>开始动画</button> <div style={{transform: scale.prop1, width: '50px', height: '50px', backgroundColor: 'red', margin: '5px'}}></div> <div style={{transform: scale.prop2, width: '50px', height: '50px', backgroundColor: 'blue', margin: '5px'}}></div> <div style={{transform: scale.prop3, width: '50px', height: '50px', backgroundColor: 'green', margin: '5px'}}></div> <div style={{transform: scale.prop4, width: '50px', height: '50px', backgroundColor: 'yellow', margin: '5px'}}></div> <div style={{transform: scale.prop5, width: '50px', height: '50px', backgroundColor: 'purple', margin: '5px'}}></div> <div style={{transform: scale.prop6, width: '50px', height: '50px', backgroundColor: 'orange', margin: '5px'}}></div> </div> ) } export default SquareAnimation;
额外优化建议
如果想让动画更简洁易维护,可以把状态改成数组形式:
const [scales, setScales] = useState(Array(6).fill('scale(0)')); // 动画函数里的更新逻辑简化为: setScales(prev => prev.map((item, idx) => idx === i-1 ? 'scale(1)' : item));
内容的提问来源于stack exchange,提问作者Tanmay Chavan
相关产品推荐
相关产品推荐

