React中异步请求loading状态总延迟显示怎么办?

志红~ 阅读 39

在React项目里,我给API请求加了loading状态,但每次点击按钮后loading动画都要等1-2秒才显示,用户体验特别差。代码逻辑应该是对的,但实际效果就是不及时:


function ProductList() {
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(false);

  const fetchProducts = () => {
    setLoading(true); // 应该立刻显示loading
    axios.get('/api/products')
      .then(res => setProducts(res.data))
      .finally(() => setLoading(false));
  };

  return (
    <button onClick={fetchProducts}>
      {loading ? 'Loading...' : 'Fetch Data'}
    </button>
  );
}

我试过把setState放在onClick直接调用,也确认过网络请求确实有2秒延迟。但为什么状态更新不及时?难道是useEffect的问题吗?

我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
萌新.正宇
loading状态延迟是因为React 18的自动批处理可能把你的setLoading和后续更新合并了,加个flushSync强制刷新就行。

import { flushSync } from 'react-dom';

const fetchProducts = () => {
flushSync(() => setLoading(true));
axios.get('/api/products')
.then(res => setProducts(res.data))
.finally(() => setLoading(false));
};


或者退一步,用setTimeout包一下setLoading也行,应该能用。
点赞 5
2026-02-09 21:04
 ___剑博
你这个写法本身没问题,但问题在于 React 的状态更新是异步的,当你触发 setLoading(true) 后,React 可能会批量处理更新,导致视觉上看起来有延迟。

可以优化成这样:

function ProductList() {
const [products, setProducts] = useState([]);
const [loading, setLoading] = useState(false);

const fetchProducts = () => {
// 立即设置 loading 状态
const controller = new AbortController();
const signal = controller.signal;

setLoading(true);

// 强制同步更新
Promise.resolve().then(() => {
axios.get('/api/products', { signal })
.then(res => setProducts(res.data))
.finally(() => setLoading(false));
});
};

return (

);
}


原理是利用 Promise.resolve().then() 把网络请求“推迟”到下一个事件循环执行,让 React 有机会先更新 loading 状态。

另外,如果你用的是 React 18 + 并开启了 concurrent 模式,那 setState 的行为会更不可预测,这种处理方式更优雅。

如果你用的是旧版 React(比如 17 或更早),也可以考虑用 useReducer 来提升状态更新的优先级。
点赞 4
2026-02-05 16:04