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

React中POST API请求时加载器的显示与关闭实现

React表单提交加载状态优化实现

现有代码问题

当前逻辑在提交函数执行初始就直接开启加载状态,若后续表单校验失败直接return,会导致加载提示错误弹出;同时表单事件绑定方式不规范,容易触发默认页面刷新行为。

优化逻辑

  • 所有表单校验、必填字段非空判断全部前置,只有全部校验通过后,才执行setSpinner(true)开启加载提示,从根本上避免校验失败时误显示加载状态
  • 保留finally代码块的加载状态重置逻辑:无论API请求成功、返回错误、还是抛出网络异常,finally块都会在请求结束后执行,自动将加载状态设为false关闭提示,完全覆盖所有请求结束场景
  • 修正表单提交绑定逻辑:将提交事件绑定在<form>标签上,同时阻止默认表单提交行为,避免页面意外刷新

修正后完整代码

const [spinner, setSpinner] = useState(false);

const handleSubmit = async (e) => {
  // 阻止表单默认提交刷新页面行为
  e.preventDefault();

  // 1. 前置校验:先校验表单有效性、必填字段非空,校验不通过直接终止,不开启加载
  const isFormValid = formRef.current?.reportValidity();
  // 此处可额外增加自定义非空判断,参考示例:
  // const isRequiredFieldFilled = name.trim() && phone.trim() && email.trim() && cart.length > 0;
  if (!isFormValid /* || !isRequiredFieldFilled */) {
    return;
  }

  // 2. 校验全部通过后,才开启加载提示
  setSpinner(true);

  // You'll probably want to invalidate this token and create a new one
  const token = process.env.React_App_Sandbox_Api;
  const data = {
    transactionReference: "string",
    paymentMethod: "CreditCard",
    checkoutOrderUrl: "http://localhost:3000/transaction",
    user: {
      name,
      msisdn: phone,
      email: email,
    },
    payementMethodDetail: {
      RedirectUrl: "http://localhost:3000/transaction",
      PurchaseEventWebhookUrl: "http://www.test.com",
    },
    bundle: cart.map((item) => ({
      ProductCode: `${item.ProductCode}`,
      Amount: item.amount,
      CurrencyCode: item.currencyCode,
      Quantity: item.quantity,
    })),
  };
  const requestOptions = {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`,
    },
    body: JSON.stringify(data),
  };

  try {
    const res = await fetch("https://api.flash-internal.flash-group.com/ecommerceManagement/1.0.0/api/checkout/",
      requestOptions
    );
    if (!res.ok) {
      // 自定义错误处理逻辑
      return;
    }
    setResponse(await res.json());
    navigate("/payment");
  } finally {
    // 3. 无论请求成功/失败,只要请求结束就关闭加载提示
    setSpinner(false);
  }
}

return (
  <>
    {/* 绑定formRef和提交事件,不要给按钮单独绑点击事件 */}
    <form ref={formRef} onSubmit={handleSubmit}>
      {/* 输入字段建议加上required属性,配合reportValidity自动完成基础非空校验 */}
    </form>  
    {spinner && <p>something is loading</p>}
    <button type="submit">Submit</button> 
  </> 
);

补充说明

  • 如果你需要自定义非空校验规则,只需要把判断逻辑加在前置校验的位置,校验不通过直接return即可,不会触发加载提示
  • finally块的执行时机晚于try和catch块,哪怕请求过程中抛出网络异常、代码报错,都会保证加载状态被正确重置,不会出现加载提示一直显示的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:51:20