I'm facing an issue with passing form data to my API endpoint in nextJS. I have set up the form using Formik and Yup for validation. Oddly, when I check the console on the client side, I can see the user input values just fine, but on the server side, these values appear as undefined. Additionally, upon inspecting the request object in the console, I noticed that the body is empty and bodyUsed is false. Here's a snippet of my client-side component:
"use client";
import React, { useState } from "react";
import { useFormik } from "formik";
import * as yup from "yup";
import FormGroup from "../(components)/FormGroup";
const Contact = () => {
const [loading, setLoading] = useState(false);
const [processed, setProcessed] = useState(false);
const formik = useFormik({
initialValues: {
firstName: "",
lastName: "",
email: "",
message: "",
},
onSubmit: async (values) => {
try {
setLoading(true);
const res = await fetch("http://localhost:3000/api/Contact", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(values, null, 2),
});
console.log(res);
if (res.ok) {
setProcessed(true);
setLoading(false);
}
} catch (error) {
console.log("Error processing message: ", error);
setLoading(false);
}
},
validationSchema: yup.object({
firstName: yup.string().trim().required("First Name is required"),
lastName: yup.string().trim().required("Last Name is required"),
email: yup
.string()
.email("Must be a valid email")
.required("Email is required"),
message: yup.string().trim().required("Message is required"),
}),
});
return (
<div className="min-h-screen flex flex-col justify-start items-center w-full mx-auto mt-24">
{processed && (
<p className="text-lg font-semibold justify-self-center">
Thank you for contacting us! We'll get back to you shortly.
</p>
)}
{!processed && (
<form
className="flex flex-col space-y-2"
onSubmit={formik.handleSubmit}
>
<div className="w-full flex space-x-2">
<div className="flex flex-col">
<FormGroup
inputLabel={"First Name:"}
placeholder={"First Name"}
name={"firstName"}
value={formik.values.firstName}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.errors.firstName && (
<p className="text-sm text-pink-600 mt-1">
{formik.errors.firstName}
</p>
)}
</div>
<div className="flex flex-col">
<FormGroup
inputLabel={"Last Name:"}
placeholder={"Last Name"}
name={"lastName"}
value={formik.values.lastName}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.errors.lastName && (
<p className="text-pink-600 text-sm mt-1">
{formik.errors.lastName}
</p>
)}
</div>
</div>
<div className="mt-2">
<FormGroup
inputLabel={"Email:"}
placeholder={"Email"}
name={"email"}
value={formik.values.email}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.errors.email && (
<p className="text-pink-600 text-sm mt-1">
{formik.errors.email}
</p>
)}
</div>
<label htmlFor="message">Message:</label>
<textarea
cols={4}
rows={4}
placeholder="Message"
name="message"
className="rounded-md px-2 py-3 shadow-sm text-black"
value={formik.values.message}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
/>
{formik.errors.message && (
<p className="text-pink-600 text-sm mt-1">
{formik.errors.message}
</p>
)}
<button
disabled={loading}
type="submit"
className="px-3 py-2 bg-green-500 rounded-lg shadow-sm mt-2 hover:bg-green-600"
>
{loading ? "Submitting..." : "Submit"}
</button>
</form>
)}
</div>
);
};
export default Contact;
And here's a snippet of the server-side component:
import Contact from "@/app/(models)/Contact";
import { NextResponse } from "next/server";
export async function POST(req) {
const { firstName, lastName, email, message } = await req.body;
try {
const newContact = await Contact.create({
firstName,
lastName,
email,
message,
});
if (newContact) {
return NextResponse.json(
{
message:
"Successfully received your message. We will respond shortly!",
},
{ status: 201 }
);
}
} catch (error) {
return NextResponse.json({ message: "Error!", error }, { status: 500 });
}
}