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
相关产品推荐
相关产品推荐

