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

为何能用useState在异步请求中管理加载状态?

异步事件处理中useState状态更新的困惑

我观察到有人在async/await函数中使用useState处理fetch请求时的加载状态。如下代码中,点击提交后loggingIn会被设为true,login函数执行完成后又被设为false,可据此展示加载spinner。

const [logginIn, setLogginIn] = useState(false);

async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    try {
      setLogginIn(true);
      await login(email, password);
    } catch (error) {
      if (error instanceof Error) {
        setLoginError(error.message);
      }
    } finally {
      setLogginIn(false);
    }
}

但根据React文档:

即使事件处理代码是异步的,渲染过程中状态变量的值也不会改变

我原以为两次setLogginIn会被一起执行。是因为React适配async/await分别调度两次状态更新?但我又认为状态仅随重渲染改变,事件处理函数应仅触发一次重渲染,对此我感到困惑。


解答

核心原因在于await会打断事件处理函数的同步执行流程,让React的状态更新批处理机制无法把两次setLogginIn合并。

React在同步的事件处理函数里会自动批处理状态更新——也就是把多个setState调用合并成一次重渲染,提升性能。但一旦遇到await,函数会暂停执行,此时当前的同步执行上下文结束,React会立即处理之前的setLogginIn(true),触发第一次重渲染,把加载状态设为true。

等login(email, password)这个异步操作完成后,函数才会继续执行到finally块里的setLogginIn(false),这时候是在一个新的异步上下文里,React会再次调度状态更新,触发第二次重渲染,把加载状态关掉。

所以你看到的两次状态更新会分别触发重渲染,刚好能实现加载spinner的显示和隐藏,这是完全符合React的运行逻辑的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:38:16