Next.js Typescript Netlify Forms — The no-redirect version

Ju Li
4 min readOct 14, 2021

I love Netlify and use it to host my startup Jama.ai’s landing page, which is built on Next.js & Typescript. All-round 10/10 service but its documentation and tutorials do suffer from a bit of “rest-of-the-owl” syndrome — they teach you 90% of what you need and then hand-wave the remaining 10%, forcing you down a rabbit-hole of tutorials and documentation to finish that 10%.

This is what I’m talking about:

You have a few options here, like sending people back to the homepage (and adding some kind of query parameter in the URL to trigger a “success” message of some kind), set up a function that doesn’t let users redirect at all, or you could make a dedicated page for a successful form submission. Let’s do this last option!

(source)

I don’t want to redirect my users. How do I do that???

If you have the same problem, I’m here to help. This tutorial is specifically for you if you:

  1. Have a website built on Next.js and Typescript
  2. Want to use Netlify to handle form submissions
  3. And want the form to simply show a success message without redirecting

Simple Contact Form

Let’s demonstrate with a simple contact form that asks for first name, last name and email. Once it is submitted, the form will disappear and be replaced with a success message.

We need to rely on this tutorial on form handling with a Stateful React form but make a few tweaks for it to work with Typescript.

Firstly, we need to define the state’s type.

interface FormPost {  firstname?: string  lastname?: string  email?: string}

And we’ll define the state like this:

const [state, setState] = useState<FormPost>();

Next, onSubmit and handleChange will need to be typed as follows:

const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {  fetch("/", {    method: "POST",    headers: { "Content-Type": "application/x-www-form-urlencoded" },    body: encode({ "form-name": "contact", ...state })})      .then(() => console.log("Success!"))      .catch(error => console.log(error));  event.preventDefault();  setSubmitted(true);}const handleChange = (e: React.FormEvent<HTMLInputElement>) => {  setState({    ...state,    [e.currentTarget.id]: e.currentTarget.value,  });};

And that’s how you do it! You can check out my code on Github here. Deploy on Netlify and this is what it looks like:

Submit a form and we’ll see a success message instead of a redirect:

And you can see the submitted form on Netlify:

That’s it then! Check my Github here if you just want to copy-paste code. Stay on for an easier method with form validation.

Contact Form with react-hook-form

Netlify’s contact form is convenient but the free tier only gives you 100 form submissions. So we need to make sure each submitted form is validated and no forms are wasted. This can be easily accomplished with react-hook-form, which also saves us from having to deal with handleChange function.

Simply install react-hook-form:

npm install react-hook-form

Import it:

import { useForm, SubmitHandler } from "react-hook-form";

Now we can remove the handleChange function and replace it with this:

const { register, handleSubmit, formState: { errors } } = useForm<FormPost>();

And update the onSubmit function with this:

const onSubmit: SubmitHandler<FormPost> = (data) => {  fetch("/", {    method: "POST",    headers: { "Content-Type": "application/x-www-form-urlencoded" },    body: encode({ "form-name": "contact", ...data })  })    .then(() => console.log("Success!"))    .catch(error => console.log(error));  setSubmitted(true);};

Notice that the type has changed. That’s because we will be calling it inside of handleSubmit in the form node:

<form name="contact" method="POST" data-netlify="true" onSubmit={handleSubmit(onSubmit)}>

And for every input field, we need to remove the “name” parameter and replace “onChange={handleChange}” as follows:

<input type="text" id="firstname" placeholder="First Name" {...register("firstname")} />

The register function will capture the form data, apply validation rules (if defined), and more!

As for what regex to use to validate email, I would recommend getting them from this Stackoverflow thread.

And this is what email validation looks like:

You can checkout the full code on my Github here.

Hope this has been helpful!

--

--