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

React组件提交按钮点击后.then代码未执行的问题排查与修复

问题描述

点击「Save settings」按钮时,Settings组件的onsubmit函数中,除if语句及.then块内的代码外,其余代码均正常执行,但.then块代码未运行。相关代码如下:

Settings组件代码

import React, {useRef, useState } from "react"
import { updateUser } from "../api callers/User"
import Loader from "../components/Loader/Loader"
import { useUser } from "./General"

export default function Settings(){

    let user=useUser()

    let reminderViaEmailShouldBeSendTo=useRef<HTMLInputElement|null>(null)
    let reminderViaPhoneShouldBeSendTo=useRef<HTMLInputElement|null>(null)
    let [isSavingSettings, setIsSavingSettings]=useState(false)

    function onsubmit(event:React.FormEvent<HTMLFormElement>){
        event.preventDefault();
        if (reminderViaPhoneShouldBeSendTo.current==null || reminderViaEmailShouldBeSendTo
            .current==null){
               return;
        }

        setIsSavingSettings(true)

        updateUser(user.email, {
            reminderViaPhoneShouldBeSendTo:reminderViaPhoneShouldBeSendTo.current.value,
            reminderViaEmailShouldBeSendTo:reminderViaEmailShouldBeSendTo.current.value
        }, user.authToken).then(
            x=>{
                setIsSavingSettings(false)
            }
        )

    }

    if (user.authToken==""){
        return <Loader></Loader>
    }

    if (isSavingSettings){
        return <div className="center">
            Saving settings ...
        </div>
    }

    return <form className="container" onSubmit={onsubmit}>
        <br></br>
        <label>Reminder via email should be send to</label>
        <br></br>
        <input type="email" ref={reminderViaEmailShouldBeSendTo}
        defaultValue={user.reminderViaEmailShouldBeSendTo}></input>
        <br></br>
        <br></br>
        <label>Reminder via phone should be send to</label>
        <br></br>
        <input type="text" ref={reminderViaPhoneShouldBeSendTo} defaultValue={
            user.reminderViaPhoneShouldBeSendTo
        }
        ></input>
        <br></br>
        <br></br>
        <button className="blue-button" >Save settings</button>
    </form>
}

updateUser函数代码

export function updateUser(email: string,
  object: { reminderViaEmailShouldBeSendTo?: string, reminderViaPhoneShouldBeSendTo?: string },
  authorizationToken: string) {

  return callAnApiWithSomeJson(urlOfTheServer + "users/" + email, "PUT", authorizationToken, object)
}

callAnApiWithSomeJson函数代码

export function callAnApiWithSomeJson(
  url: string,
  method: string,
  accessToken: string = "",
  json?:Object
) {
  return new Promise((resolve, reject) => {
    console.log(json);
    fetch(url, {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        'Content-Type':'application/json'
      },
      method: method,
      body: JSON.stringify(json),
      keepalive:true,
    })
      .then((result) => {result.json().then((result) => resolve(result))})
      .catch((error) => reject(error));
  });
}
原因分析
  1. fetch的HTTP错误未被捕获:fetch仅在网络故障时触发catch,对于4xx/5xx这类HTTP错误状态码,仍会进入then分支。若此时响应无法解析为JSON,result.json()会抛出错误,但该错误未被捕获,导致外层Promise永远处于pending状态,updateUser的.then回调无法执行。
  2. 手动封装Promise的错误处理缺失:callAnApiWithSomeJson手动创建Promise,但内部result.json()的错误未被处理,一旦解析失败,Promise既不会resolve也不会reject,后续逻辑彻底卡住。
  3. 未处理Promise的reject分支:onsubmit仅监听了updateUser的成功回调,未处理错误分支,若请求出错,setIsSavingSettings(false)永远不会执行,同时错误无法被排查。
修复方案

1. 完善callAnApiWithSomeJson的错误处理

去掉冗余的手动Promise封装,直接使用fetch的Promise链,同时处理HTTP错误和JSON解析错误:

export function callAnApiWithSomeJson(
  url: string,
  method: string,
  accessToken: string = "",
  json?: Object
) {
  console.log(json);
  return fetch(url, {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    method: method,
    body: JSON.stringify(json),
    keepalive: true,
  })
  .then((result) => {
    // 捕获HTTP错误状态码
    if (!result.ok) {
      throw new Error(`请求失败,状态码:${result.status}`);
    }
    return result.json();
  });
}

2. 为onsubmit添加错误处理

确保请求无论成功或失败,都能重置isSavingSettings状态:

function onsubmit(event: React.FormEvent<HTMLFormElement>) {
  event.preventDefault();
  if (reminderViaPhoneShouldBeSendTo.current == null || reminderViaEmailShouldBeSendTo.current == null) {
    return;
  }

  setIsSavingSettings(true);

  updateUser(user.email, {
    reminderViaPhoneShouldBeSendTo: reminderViaPhoneShouldBeSendTo.current.value,
    reminderViaEmailShouldBeSendTo: reminderViaEmailShouldBeSendTo.current.value
  }, user.authToken)
  .then(x => {
    setIsSavingSettings(false);
  })
  .catch(error => {
    console.error("保存设置失败:", error);
    setIsSavingSettings(false);
    // 可选:添加用户可见的错误提示,比如弹窗或文字提示
  });
}

3. 可选:用async/await简化代码

将onsubmit改为异步函数,代码逻辑更清晰:

async function onsubmit(event: React.FormEvent<HTMLFormElement>) {
  event.preventDefault();
  if (reminderViaPhoneShouldBeSendTo.current == null || reminderViaEmailShouldBeSendTo.current == null) {
    return;
  }

  setIsSavingSettings(true);
  try {
    await updateUser(user.email, {
      reminderViaPhoneShouldBeSendTo: reminderViaPhoneShouldBeSendTo.current.value,
      reminderViaEmailShouldBeSendTo: reminderViaEmailShouldBeSendTo.current.value
    }, user.authToken);
  } catch (error) {
    console.error("保存设置失败:", error);
    // 可选:添加用户错误提示
  } finally {
    // 无论成功失败都重置状态
    setIsSavingSettings(false);
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:50:43