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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 09:25:26