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

React中useEffect结合setTimeout为何重复添加字符?

React字符串逐字符重复添加问题解决方法

问题根源是React 18开发环境下的Strict Mode——它会自动执行两次带有空依赖数组的useEffect,你的定时器逻辑被触发了两次,所以每个字符会被添加两遍。

下面给两种可行的解决办法:

方法一:清理定时器

在useEffect的返回函数中清除所有定时器,避免重复执行的逻辑继续运行:

const [placeholder, setPlaceholder] = useState<string>('');

useEffect(() => {
    const str = "How may I help you today?";
    const letters = Array.from(str);
    const timerIds: number[] = [];

    const addLetterWithDelay = (index: number) => {
        if (index < letters.length) {
            const timerId = setTimeout(() => {
                setPlaceholder(prev => prev + letters[index]);
                addLetterWithDelay(index + 1);
            }, 1000);
            timerIds.push(timerId);
        }
    };

    addLetterWithDelay(0);

    // 组件卸载或重新执行useEffect时清除所有定时器
    return () => {
        timerIds.forEach(id => clearTimeout(id));
    };
}, []);

方法二:用Ref标记初始化状态

通过一个ref变量判断是否已经启动过定时器,避免重复触发:

const [placeholder, setPlaceholder] = useState<string>('');
const hasInitiated = useRef(false);

useEffect(() => {
    // 如果已经启动过,直接返回
    if (hasInitiated.current) return;
    hasInitiated.current = true;

    const str = "How may I help you today?";
    const letters = Array.from(str);

    const addLetterWithDelay = (index: number) => {
        if (index < letters.length) {
            setTimeout(() => {
                setPlaceholder(prev => prev + letters[index]);
                addLetterWithDelay(index + 1);
            }, 1000);
        }
    };

    addLetterWithDelay(0);
}, []);

注意:生产环境下Strict Mode不会触发两次执行,所以上面的方法主要是解决开发环境的重复问题。

内容的提问来源于stack exchange,提问作者Adam Basha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 15:00:07