Netlify forms submission have stopped working. It used to work for me before the stable v5 release of Nextjs.
The forms are correctly registered and submission seems submit but no data is captured.
'use client'
import { zodResolver } from '@hookform/resolvers/zod';
import axios from 'axios';
import React, { useRef, useState } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';
import { useForm, SubmitHandler } from 'react-hook-form';
import toast, { Toaster } from 'react-hot-toast';
import { z } from 'zod';
interface IContactFormInput {
name: string;
email: string;
enquiryType: string;
message: string;
agreeToTerms: boolean;
}
const schema = z.object({
'form-name': z.string().optional(),
name: z.string().min(1, 'Please enter your name'),
email: z.string().email('Please enter a valid email address'),
enquiryType: z.string().min(1, 'Please select the nature of your enquiry'),
message: z.string().min(1, 'Please enter your message'),
agreeToTerms: z.boolean().refine(val => val, 'You must agree to the Terms & Conditions')
});
export function ContactForm() {
const captchaRef: any = useRef(null)
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
const [submissionSuccess, setSubmissionSuccess] = useState<boolean>(false);
const key: string = process.env.NEXT_PUBLIC_RECAP_SITE_KEY || '';
const { register, handleSubmit, formState: { errors }, reset } = useForm<IContactFormInput>({
resolver: zodResolver(schema),
});
const onSubmit: SubmitHandler<IContactFormInput> = (data: any) => {
setIsSubmitting(true);
try {
const formData:any = new FormData();
for (const key in data) {
formData.append(key, data[key]);
}
formData.append('form-name', 'contact');
console.log('formData', new URLSearchParams(formData).toString());
fetch("/", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams(formData).toString(),
}).then((response) => {
if (response) {
setIsSubmitting(false);
setSubmissionSuccess(true);
toast.success('Your message has been sent!');
reset(); // Optionally reset form fields
}
});
} catch (error) {
console.log('error', error);
setIsSubmitting(false);
toast.error('There was an error sending your message. Please try again later.');
return;
}
};
if (submissionSuccess) {
return (<div className={'container mx-auto max-w-2xl'}>
<div className="text-center font-bold">Your message has been sent successfully! We will get back to you soon.</div>
</div>
);
}
return (
<div className="form-control w-full max-w-xl mx-auto" >
<form onSubmit={handleSubmit(onSubmit)} noValidate data-netlify="true" method="post" className="space-y-4">
<input type="hidden" name="form-name" value="contact" />
<input
type="text"
placeholder="Name"
className={`input input-bordered w-full ${errors.name ? 'input-error' : ''}`}
{...register('name')}
disabled={isSubmitting}
/>
{errors.name && <p className="text-error">{errors.name.message}</p>}
<input
type="email"
placeholder="Email"
className={`input input-bordered w-full ${errors.email ? 'input-error' : ''}`}
{...register('email')}
disabled={isSubmitting}
/>
{errors.email && <p className="text-error">{errors.email.message}</p>}
<select
className={`select select-bordered w-full ${errors.enquiryType ? 'select-error' : ''}`}
{...register('enquiryType')}
disabled={isSubmitting}
>
<option value="" disabled defaultValue="">Nature of Enquiry</option>
<option value="general">General Inquiry</option>
<option value="billing">Billing Inquiry</option>
<option value="support">Support Request</option>
<option value="feedback">Feedback</option>
<option value="other">Other</option>
</select>
{errors.enquiryType && <p className="text-error">{errors.enquiryType.message}</p>}
<textarea
placeholder="Message"
className={`textarea textarea-bordered w-full ${errors.message ? 'textarea-error' : ''}`}
{...register('message')}
rows={4}
disabled={isSubmitting}
/>
{errors.message && <p className="text-error">{errors.message.message}</p>}
<div className="flex items-center gap-2">
<div className="grow w-full">
<div className="flex items-center gap-2">
<input
type="checkbox"
className={`checkbox ${errors.agreeToTerms ? 'checkbox-error' : ''}`}
{...register('agreeToTerms')}
id="agreeToTerms"
/>
<label htmlFor="agreeToTerms" className="label-text">I agree to the Terms & Conditions</label>
</div>
{errors.agreeToTerms && <p className="text-error">{errors.agreeToTerms.message}</p>}
</div>
<div className="shrink flex w-full justify-end">
{/* Submit Button */}
<button type="submit" className={`btn btn-primary ${isSubmitting ? 'loading' : ''}`}
disabled={isSubmitting}>
{isSubmitting ? 'Sending...' : 'Send Message'}
</button>
</div>
</div>
</form>
<Toaster />
</div>
);
}
export default ContactForm;
I also get an error on my local server when submitting:
Error: Failed to find Server Action "null". This request might be from an older or newer deployment. Original error: Invariant: Missing 'next-action' header.
at rw (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:39:1703)
at /Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:38:8843
at AsyncLocalStorage.run (node:async_hooks:346:14)
at rS (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:38:8051)
at r2 (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:41:1257)
at /Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:42:697
at AsyncLocalStorage.run (node:async_hooks:346:14)
at Object.wrap (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:36:16575)
at /Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:42:616
at AsyncLocalStorage.run (node:async_hooks:346:14)
at Object.wrap (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:36:15721)
at r4 (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:42:543)
at nf.render (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/compiled/next-server/app-page.runtime.dev.js:42:4608)
at doRender (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:1433:44)
at cacheEntry.responseCache.get.routeKind (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:1594:34)
at ResponseCache.get (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/response-cache/index.js:49:26)
at DevServer.renderToResponseWithComponentsImpl (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:1502:53)
at /Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:997:121
at NextTracerImpl.trace (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/lib/trace/tracer.js:105:20)
at DevServer.renderToResponseWithComponents (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:997:41)
at DevServer.renderPageComponent (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:1919:35)
at async DevServer.renderToResponseImpl (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:1957:32)
at async DevServer.pipeImpl (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:915:25)
at async NextNodeServer.handleCatchallRenderRequest (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/next-server.js:272:17)
at async DevServer.handleRequestImpl (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/base-server.js:811:17)
at async /Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/dev/next-dev-server.js:339:20
at async Span.traceAsyncFn (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/trace/trace.js:154:20)
at async DevServer.handleRequest (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/dev/next-dev-server.js:336:24)
at async invokeRender (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/lib/router-server.js:174:21)
at async handleRequest (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/lib/router-server.js:353:24)
at async requestHandlerImpl (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/lib/router-server.js:377:13)
at async Server.requestListener (/Users/olafsiebert/html/myelementalbeing/node_modules/next/dist/server/lib/start-server.js:141:13)
My root layout contains the hidden forms:
return (<>
<Header />
{children}
<Footer />
<form name="contact" data-netlify="true" hidden>
<input type="text" name="name" />
<input type="email" name="email" />
<input type="enquiryType" name="enquiryType" />
<input type="agreeToTerms" name="agreeToTerms" />
<textarea name="message" />
</form>
<form name="review" data-netlify="true" hidden>
<input type="text" name="name" />
<input type="email" name="email" />
<input type="product_id" name="product_id" />
<input type="product_type" name="product_type" />
<input type="agreeToTerms" name="agreeToTerms" />
<textarea name="reviewBody" />
</form>
</>
)
}