So I have a sign up form using react-hook-form
and I want to make the submit input
disabled and display a "Signing in..." message. I've console logged the isSubmitting
value within the render and that shows true
when I submit and then false
not long after however the submit button
within the form never updates to reflect the isSubmitting
status.
What am I doing wrong? Here is the React Hook Form useFormState docs
From what I can see it should work?
Thanks in advance.
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
I think you need to refactor your onSubmit
function to make it async
so isSubmitting
will stay true
during your signIn
call.
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)
})
}
onSubmit
needs to return a Promise
for formState
to update correctly.
const onSubmit = (payload) => {
// You need to return a promise.
return new Promise((resolve) => {
setTimeout(() => resolve(), 1000);
});
};
References:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With