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

React中useState更新字符串异常:打字效果丢失第二个字符

打字效果丢失第二个字符的问题排查与修复

我想实现打字效果,但第二个字符总是无法显示。比如要输出"Hello World",实际显示成"Hllo World"。我的代码如下:

export default function Error({ errorMsg }) {
    const [errorString, setErrorString] = useState("");
    let i = 0;

    useEffect(() => {
        writeError();
    }, []);

    function writeError() {
        let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

        setTimeout(() => {
            if (i < errorMsg.length) {
                setErrorString(errorString => ([
                    ...errorString,
                    errorMsg.charAt(i)
                ]));
                i++;
                return writeError();
            }
        }, timer);
    }

    return (
        <div>
            <div id="wrp">
                <div>{errorString}</div>
            </div>
        </div>
    );
}

问题原因

问题出在闭包对变量i的引用以及React状态更新的执行时机上:

  • setErrorString的更新回调是闭包,它捕获的是i变量的引用,而非调用setErrorString时的i值。
  • 原代码中调用setErrorString后立即执行i++,若更新回调被延迟执行(比如React批处理更新场景),回调执行时i已经是自增后的值,导致本该添加的第二个字符(i=1对应的字符)被跳过,直接使用了i=2时的字符。

修复方案

将i++移至charAt方法调用中,确保获取当前字符的同时立即自增i,避免闭包引用带来的变量值不一致问题:

export default function Error({ errorMsg }) {
    const [errorString, setErrorString] = useState("");
    let i = 0;

    useEffect(() => {
        writeError();
    }, []);

    function writeError() {
        let timer = Math.floor(Math.random() * (100 - 25 + 1)) + 25;

        setTimeout(() => {
            if (i < errorMsg.length) {
                setErrorString(errorString => ([
                    ...errorString,
                    errorMsg.charAt(i++) // 在这里自增i,确保取值与自增同步
                ]));
                return writeError();
            }
        }, timer);
    }

    return (
        <div>
            <div id="wrp">
                <div>{errorString}</div>
            </div>
        </div>
    );
}

这样修改后,charAt(i++)会先获取当前i对应的字符,再立即将i自增,无论更新回调何时执行,都能保证取到正确位置的字符,不会出现字符丢失的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:21:26