I’m working on a registration form in Next.js and I’m trying to redirect the user to an OTP verification page after successful registration. However, the router.push
is not working as expected when the form is submitted. Here is my code:
"use client"
import React, { useState } from "react";
import Link from "next/link";
import { useForm } from "react-hook-form";
import styles from "./registerForm.module.css";
import { motion } from "framer-motion";
import { useRouter } from "next/navigation";
import apiLinks from "@/api/api-links";
import { POST } from "@/api/api-calls";
const RegisterForm = () => {
const { register, handleSubmit, formState: { errors }, getValues } = useForm();
const router = useRouter();
const [isLoading, setIsLoading] = useState(false);
const onSubmit = async (data) => {
setIsLoading(true);
try {
const response = await POST({ path: apiLinks['auth']['register'], body: data });
router.push(`/otp/${data.email}`);
} catch (error) {
if (error.response) {
// Handle HTTP errors
console.error('HTTP Error:', error.response.data);
} else {
// Handle non-HTTP errors (e.g., network error)
console.error('Error:', error.message);
}
}
setIsLoading(false);
};
return (
<motion.div
initial={{ y: "5vh", opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.9, ease: "easeOut" }}
style={{ overflow: "hidden" }}
className={styles.formContainer}
>
<h1 className={styles.text}>Register</h1>
<form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
<label>First Name</label>
<input
type="text"
name="firstName"
placeholder="E.g. John"
className={`${styles.input} ${errors.firstName ? styles.errorInput : ""}`}
{...register("firstName", {
required: "First name is required",
pattern: {
value: /^[A-Za-z]+$/,
message: "First name should only contain letters",
},
})}
/>
{errors.firstName && (
<span className={styles.errorMessage}>{errors.firstName.message}</span>
)}
<label>Last Name</label>
<input
type="text"
name="lastName"
placeholder="E.g. Doe"
className={`${styles.input} ${errors.lastName ? styles.errorInput : ""}`}
{...register("lastName", {
required: "Last name is required",
pattern: {
value: /^[A-Za-z]+$/,
message: "Last name should only contain letters",
},
})}
/>
{errors.lastName && (
<span className={styles.errorMessage}>{errors.lastName.message}</span>
)}
<label>Phone Number</label>
<input
type="tel"
name="phoneNumber"
placeholder="E.g. 123-456-7890"
className={`${styles.input} ${errors.phoneNumber ? styles.errorInput : ""}`}
{...register("phoneNumber", {
required: "Phone number is required",
pattern: {
value: /^d{3}-d{3}-d{4}$/,
message: "Phone number must be in the format 123-456-7890",
},
})}
/>
{errors.phoneNumber && (
<span className={styles.errorMessage}>{errors.phoneNumber.message}</span>
)}
<label>Email</label>
<input
type="text"
name="email"
placeholder="E.g [email protected]"
className={`${styles.input} ${errors.email ? styles.errorInput : ""}`}
{...register("email", {
required: "Email is required",
pattern: {
value: /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,}$/,
message: "Invalid email address",
},
})}
/>
{errors.email && (
<span className={styles.errorMessage}>{errors.email.message}</span>
)}
<label>Password</label>
<input
type="password"
name="password"
placeholder="Password"
className={`${styles.input} ${errors.password ? styles.errorInput : ""}`}
{...register("password", {
required: "Password is required",
minLength: {
value: 8,
message: "Password must be at least 8 characters",
},
})}
/>
{errors.password && (
<span className={styles.errorMessage}>{errors.password.message}</span>
)}
<label>Repeat Password</label>
<input
type="password"
name="repeatPassword"
placeholder="Repeat Password"
className={`${styles.input} ${errors.repeatPassword ? styles.errorInput : ""}`}
{...register("repeatPassword", {
required: "Repeat Password is required",
validate: {
matchesPassword: (value) =>
value === getValues("password") || "Passwords do not match",
},
})}
/>
{errors.repeatPassword && (
<span className={styles.errorMessage}>{errors.repeatPassword.message}</span>
)}
<button type="submit" disabled={isLoading}>
{isLoading ? "Registering..." : "Register"}
</button>
<div className={styles.registerContainer}>
Already have an account?
<Link href="/login" className={styles.loginLink}>
Login
</Link>
</div>
</form>
</motion.div>
);
}
export default RegisterForm;
Details:
- I’m using
useRouter
fromnext/navigation
to navigate to the OTP page. - The registration form data is being sent via a POST request using a custom
POST
function. - On successful registration, I attempt to navigate to
/otp/[email]
usingrouter.push(
/otp/${data.email})
. - However, the navigation is not happening after the form submission.
What I have checked:
- The POST request is working correctly and returns a successful response.
- The
data.email
contains the correct email address. - There are no errors in the console related to the navigation.
Question:
Why is router.push
not working as expected? Is there something I’m missing or doing wrong in my code? Any help would be greatly appreciated!