为什么表单状态不会在使用 React 表单挂钩的提交按钮内明显改变?

Why won't the form state visibly change within the submit button using react form hook?

所以我有一个使用 react-hook-form 的注册表单,我想禁用 submit input 并显示“正在登录...”消息。我已经在控制台中记录了渲染中的 isSubmitting 值,当我提交时显示 true,然后不久之后显示 false 但是表单中的 submit button 永远不会更新以反映isSubmitting 状态。

我做错了什么? Here is the React Hook Form useFormState docs

据我所知,它应该有效吗?

提前致谢。

import { useState } from "react"
import { useForm, useFormState } from "react-hook-form"
import useAuth from "Hooks/useAuth"

const SignInForm = () => {
  const [firebaseError, setFirebaseError] = useState(null)
  const { signIn } = useAuth()
  const {
    register,
    handleSubmit,
    resetField,
    control,
    formState: { errors },
  } = useForm()

  const { isSubmitting, isValidating } = useFormState({ control })

  const onSubmit = (data) => {
    signIn(data.email, data.password)
      .then((response) => console.log(response))
      .catch((error) => {
        let message = null

        if (error.code === "auth/too-many-requests") {
          message =
            "Too many unsuccessful attempts, please reset password or try again later"
        }

        if (error.code === "auth/wrong-password") {
          message = "Incorrect password, please try again"
        }

        if (error.code === "auth/user-not-found") {
          message = "User does not exist, please try again"
        }

        resetField("password")
        setFirebaseError(message)
      })
  }

  return (
    <form
      className="signupForm"
      onSubmit={handleSubmit(onSubmit)}
      autoComplete="off"
    >
      {console.log(isSubmitting)}
      {firebaseError && (
        <p className="form-top-error has-text-danger">{firebaseError}</p>
      )}

      <div className="field">
        <input
          type="text"
          className="input formInput"
          placeholder="Email"
          {...register("email", {
            required: {
              value: true,
              message: "Field can not be empty",
            },
            pattern: {
              value:
                /^(([^<>()[\]\.,;:\s@"]+(\.[^<>()[\]\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
              message: "Invalid email",
            },
          })}
        />
        {errors.email && (
          <span className="is-block has-text-danger is-size-7">
            {errors.email?.message}
          </span>
        )}
      </div>
      <div className="field">
        <input
          type="password"
          className="input formInput"
          placeholder="Password"
          {...register("password", {
            required: "Field can not be empty",
            minLength: {
              value: 6,
              message: "Must be longer than 6 characters",
            },
          })}
        />
        {errors.password && (
          <span className="is-block has-text-danger is-size-7">
            {errors.password?.message}
          </span>
        )}
      </div>
      <input
        type="submit"
        className="button is-info"
        value={isSubmitting ? "Signing In..." : "Sign In"}
        disabled={isSubmitting}
      />
    </form>
  )
}

export default SignInForm

我认为您需要重构您的 onSubmit 函数以使其 async 因此 isSubmitting 在您的 signIn 调用期间将保持 true

const onSubmit = async (data) => {
    await signIn(data.email, data.password)
      .then((response) => console.log(response))
      .catch((error) => {
        let message = null

        if (error.code === "auth/too-many-requests") {
          message =
            "Too many unsuccessful attempts, please reset password or try again later"
        }

        if (error.code === "auth/wrong-password") {
          message = "Incorrect password, please try again"
        }

        if (error.code === "auth/user-not-found") {
          message = "User does not exist, please try again"
        }

        resetField("password")
        setFirebaseError(message)
      })
  }