This is my login page (I use Next.js 14) below.
when setSubmitting true – loading spinner render on the page, but for some reason before page actually routes to / home page isSubmitting became false and form again shows for a second before routing.
"use client";
import UnderlinedInput from "@/components/underlined-input";
import { Button, cn } from "@nextui-org/react";
import { FormikHelpers, useFormik } from "formik";
import { useRouter } from "next/navigation";
import { object, string } from "yup";
import Link from "next/link";
import { useAppDispatch } from "@/hooks/store";
import { loginUser } from "@/store/auth/authSlice";
import LoadingSpinner from "@/components/loading-spinner";
interface InitialValues {
email: string;
password: string;
}
const validationSchema = object({
email: string().email().required("email is required"),
password: string().min(5).max(20).required("password is required"),
});
const Login = () => {
const router = useRouter();
const dispatch = useAppDispatch();
const {
errors,
values,
handleSubmit,
handleChange,
handleBlur,
isSubmitting,
touched,
} = useFormik<InitialValues>({
initialValues: {
email: "",
password: "",
},
validationSchema,
onSubmit: onSubmit,
});
async function onSubmit(
values: InitialValues,
{ setSubmitting, resetForm, setErrors }: FormikHelpers<InitialValues>
) {
try {
setSubmitting(true);
await dispatch(loginUser(values)).unwrap();
router.push("/");
} catch (error) {
console.log(error);
setErrors({
email: "invalid email or password",
password: "invalid email or password",
});
} finally {
setSubmitting(false);
}
}
if (isSubmitting) {
return <LoadingSpinner />;
}
return (
<div>
//form structure
</div>
);
};
export default Login;
ps:
I was trying use simple Promise with timeout instead of dispatching async thunk but problem is not in it
2
Answers
You’ll need to
await
on the line where you’re usingrouter.push("/")
. The reason is due to the asynchronous nature ofrouter.push("/")
. When thesetSubmitting(false)
line is executed, theisSubmitting
becomes false, and the form is shown again before the navigation completes.You should wait for the dispatch(loginUser(values)).unwrap() to complete before setting isSubmitting to false, By using await before the dispatch call, you ensure that the setSubmitting(false) is only executed after the dispatch operation is complete.:-