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

React中useState setter在函数内无法实时反射值的问题求助

React表单验证首次提交状态判断异常问题

问题描述

在函数中同时读取和设置React useState状态值做表单验证,点击提交按钮触发onSubmit函数时,首次点击即便存在验证错误,仍会判定表单有效,第二次点击才能得到正确结果。

代码示例

const [bookingToDateError, setBookingToDateError] = useState<string | undefined>();
const [bookingFromDateError, setBookingFromDateError] = useState<string | undefined>();


const onSubmit: SubmitHandler<FormFields> = async (data) => {
   await validating(data);
   await submitBooking();
};


const validating = async (data: FormFields) => {
    const timeNow = new Date();
    const bookingFromDate = new Date(data.bookingfromdate);
    const bookingToDate = new Date(data.bookingtodate);

    if (dateIsBefore(bookingFromDate, timeNow) === true) {
      setBookingFromDateError("Date and time cannot before current datetime");
    } else {
      setBookingFromDateError(undefined);
    }

    if (dateIsBefore(bookingToDate, timeNow) === true) {
      setBookingToDateError("Date and time cannot before current datetime");
    } else {
      setBookingToDateError(undefined);
    }
};



const submitBooking = async () => {
    if (
      bookingFromDateError === undefined &&
      bookingToDateError === undefined
    ) {
      console.log("Form is valid, can proceed");
      // I can call api here
    } else {
      console.log("Form is not valid, cannot proceed");
      // show error message cuz form is not valid
    }
};

问题原因

React的useState状态更新是异步的,validating函数里调用setBookingFromDateError和setBookingToDateError后,状态并不会立刻更新。此时立刻调用submitBooking,读取到的还是更新前的旧状态,所以首次提交会判断错误。

解决方案

方案1:让验证函数直接返回验证结果

不依赖状态值判断表单有效性,在validating中直接返回验证状态,同时更新状态用于页面错误展示:

const [bookingToDateError, setBookingToDateError] = useState<string | undefined>();
const [bookingFromDateError, setBookingFromDateError] = useState<string | undefined>();


const onSubmit: SubmitHandler<FormFields> = async (data) => {
   const isValid = await validating(data);
   if (isValid) {
     await submitBooking();
   } else {
     console.log("Form is not valid, cannot proceed");
   }
};


const validating = async (data: FormFields): Promise<boolean> => {
    const timeNow = new Date();
    const bookingFromDate = new Date(data.bookingfromdate);
    const bookingToDate = new Date(data.bookingtodate);

    let fromError: string | undefined;
    let toError: string | undefined;

    if (dateIsBefore(bookingFromDate, timeNow) === true) {
      fromError = "日期和时间不能早于当前时间";
    }

    if (dateIsBefore(bookingToDate, timeNow) === true) {
      toError = "日期和时间不能早于当前时间";
    }

    setBookingFromDateError(fromError);
    setBookingToDateError(toError);

    return fromError === undefined && toError === undefined;
};



const submitBooking = async () => {
    console.log("Form is valid, can proceed");
    // 在这里调用API
};

方案2:使用useEffect监听错误状态

如果必须依赖状态值判断,可通过useEffect监听错误状态变化,待状态更新后再执行提交逻辑:

const [bookingToDateError, setBookingToDateError] = useState<string | undefined>();
const [bookingFromDateError, setBookingFromDateError] = useState<string | undefined>();
const [isValidationDone, setIsValidationDone] = useState(false);


const onSubmit: SubmitHandler<FormFields> = async (data) => {
   setIsValidationDone(false);
   await validating(data);
   setIsValidationDone(true);
};


const validating = async (data: FormFields) => {
    const timeNow = new Date();
    const bookingFromDate = new Date(data.bookingfromdate);
    const bookingToDate = new Date(data.bookingtodate);

    if (dateIsBefore(bookingFromDate, timeNow) === true) {
      setBookingFromDateError("日期和时间不能早于当前时间");
    } else {
      setBookingFromDateError(undefined);
    }

    if (dateIsBefore(bookingToDate, timeNow) === true) {
      setBookingToDateError("日期和时间不能早于当前时间");
    } else {
      setBookingToDateError(undefined);
    }
};

useEffect(() => {
  if (isValidationDone) {
    if (bookingFromDateError === undefined && bookingToDateError === undefined) {
      submitBooking();
    } else {
      console.log("Form is not valid, cannot proceed");
    }
    setIsValidationDone(false);
  }
}, [isValidationDone, bookingFromDateError, bookingToDateError]);


const submitBooking = async () => {
    console.log("Form is valid, can proceed");
    // 在这里调用API
};

总结

优先推荐方案1,逻辑更直接,避免了异步状态更新带来的时序问题,同时能正常更新错误状态用于页面展示。

内容的提问来源于stack exchange,提问作者Marcus Neo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 14:00:56