Back

Step-by-Step Guide: Creating a Contact Form in Next.js with Netlify Forms

Step-by-Step Guide: Creating a Contact Form in Next.js with Netlify Forms

As a website owner, having a contact form that is easy to use and ensures the safety of your visitors’ information is crucial. A well-designed contact form is a great way to engage with potential customers and build trust with your audience. By the end of this guide, you’ll have a fully functional contact form based on Netlify Forms, integrated into your Next.js application, enabling you to easily receive and manage user inquiries.

Creating an effective and reliable contact form is crucial in the modern age of online business. It’s essential to provide a secure and convenient way for visitors to contact you, and a contact form is the perfect solution. By implementing a contact form, you can streamline your communication process and make it easy for visitors to contact you with any questions or concerns. We will look at how to leverage Nextjs in this tutorial, a popular React framework known for its server-side rendering and seamless developer experience, in combination with Netlify Forms, a powerful form-handling service provided by Netlify.

Set Up Development Environment

We would like to set up our Next.js environment before we start by using the command line below.

npx create-next-app@latest

Follow the prompt as stated below: -

After that, our Next App is ready, so we move to our editor, where the most work is done. We can check out our tree structure below.

form-app
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── src
  └── app
    ├── favicon.ico
    ├── globals.css
    ├── layout.js
    └── page.js
└── tailwind.config.js

Creating the Contact Form Component

In this article, we have three methods to implement the integration of Netlify Forms with Next.js; first of all, we’ll have to look at the simplified approach while we move on to other methods. To create our Form Component, we’ll navigate to our layout.js file.

export default function RootLayout({ children }) {
 return (
  <html lang="en">
   <body className={inter.className}>{children}</body>
  </html>
 );
}

Under the html tag, we’ll create a form field with various tags and attributes such as label and input.

//layout.js//
export default function RootLayout({ children }) {
 return (
  <html lang="en">
   <body className={inter.className}>
    {children}
    <div>
     <h2>Contact us!</h2>
     <form>
      <div>
       <label for="name">Name</label>
       <input type="text" id="name" name="name" />
      </div>
      <div>
       <label for="email">Email</label>
       <input type="email" id="email" name="email" />
      </div>
      <div>
       <label for="message">Message</label>
       <textarea id="message" name="message" rows="4"></textarea>
      </div>
      <button type="submit">Submit</button>
     </form>
    </div>
   </body>
  </html>
 );
}

There aren’t many gimmicks on this form; it’s pretty basic. Go to localhost:3000 after launching your application (usually with npm run dev). You should see a little bit that resembles this, depending on how you styled it: -

Currently, if you tried deploying this to Netlify at this time, nothing would happen. It is a straightforward form without any connections to make the form field do anything. So let’s change that.

Adding Netlify Attributes to our Form

Let’s return to the layout.js and add the Netlify attributes to the form tag, which helps link the form to the Netlify server. For clarification, the attributes are netlify, data-netlify='true', and netlify='true'. Understand that they all work the same way, so whichever you choose to use works perfectly.

  //layout.js//
export default function RootLayout({ children }) {
 return (
  <html lang="en">
   <body className={inter.className}>
    {children}
    <div>
     <h2>Contact us!</h2>
     <form name="contact" method="post" netlify>
      <input type="hidden" name="form-name" value="contact" />
      <div>
       <label for="name">Name</label>
       <input type="text" id="name" name="name" />
      </div>
      .....
     </form>
    </div>
   </body>
  </html>
 );
}

After this, we save and deploy to Netlify and move on to the next step, enabling form in Netlify.

Handling Form Submissions

You can manage forms with Netlify’s serverless form management without making additional API calls or adding complex JavaScript code. Once turned on, the built-in form recognition capability enables their build system to parse your HTML automatically at deployment time, eliminating the need for you to use an API or add state functions. To begin with, we have to enable the automatic form detection system in the site configuration on the Netlify website. -

Now we’re done with the steps, so whenever a visitor visits your site and decides to submit a form, they get a success message below indicating that Netlify has received their message. -

If we move to Netlify and our site dashboard, under form submission, we see a list of forms submitted by visitors to our site. -

To be fair, this method is mainly for static sites, such as a site that includes HTML (Next.js is one of them). When a site is deployed, the processing bots search for the netlify attributes, which they can only understand in HTML form. So if we say we have a Next app that we would like to deploy to production, this form won’t work by adding the said attributes to the JSX form because they can’t detect forms rendered with Javascript. With that said, we can apply two other methods to make Netlify understand our form field with its attributes on a Javascript file: Stateless and Stateful Components Form.

Stateless Component

For our Stateless React component, all we have to do is add a static html form field with a hidden attribute.

<form name="contact" netlify="true" hidden>
 <input type="text" name="name" />
 <input type="email" name="email" />
 <textarea name="message"></textarea>
</form>;

In this case, we’ll add it to our layout.js cause it has a html tag within. Because we will add a hidden property to the form to make it invisible to users and screen readers, you can remove the label and submit components.

Add a Hidden Input tag in the JSX Form

In your JSX form, you must additionally include a hidden type element with the name and value properties shown in the code below:

<input type="hidden" name="form-name" value="contact" />

Now, your Pages.js file ought to seem like follows:

export default function Home() {
 return (
  <div>
   <h2>Contact Us</h2>
   <form name="contact" method="post">
    <input type="hidden" name="form-name" value="contact" />
    <div>
     <label htmlFor="name">Name</label>
     <input type="text" id="name" name="name" />
    </div>
    <div>
     <label htmlFor="email">Email</label>
     <input type="email" id="email" name="email" />
    </div>
    <div>
     <label htmlFor="message">Message</label>
     <textarea id="message" name="message" rows="4"></textarea>
    </div>
    <button type="submit">Submit</button>
   </form>
  </div>
 );
}

You should be able to see the form if you run the app in the browser; when your app has been deployed to Netlify, can you submit forms.

Stateful Component

In this case, we’ll create a Contact.js file containing our state function, and then import it to our page.js. As for the layout.js, it remains hidden.

//Contact.js//
const encode = (data) => {
 return Object.keys(data)
  .map((key) => encodeURIComponent(key) + "=" + encodeURIComponent(data[key]))
  .join("&");
};
const Contact = () => {
 const [formData, setFormData] = useState({
  name: "",
  email: "",
  message: "",
 });
const handleSubmit = (e) => {
  e.preventDefault();
  fetch("/", {
   method: "POST",
   headers: { "Content-Type": "application/x-www-form-urlencoded" },
   body: encode({ "form-name": "contact", ...formData }),
  })
   .then(() => alert("Success!"))
   .catch((error) => alert(error));
 };
const handleChange = (e) => {
  const { name, value } = e.target;
  setFormData((prevData) => ({
   ...prevData,
   [name]: value,
  }));
 };
 return (
  <div>
   <h2>Contact Us</h2>
   <form onSubmit={handleSubmit}>...</form>
  </div>
 );
};
export default Contact;

The encode function converts the form data into a URL-encoded string. It takes an object (data) as input, iterates through its keys, and encodes both the key and its corresponding value. The resulting encoded key-value pairs are then joined with ’&’ to form a URL-encoded string. The main functional component, Contact, uses the useState React hook to initialize and manage the form data state. The formData state holds the values for name, email, and message inputs. The handleChange function is called whenever there’s a change in any of the input fields. It updates the form data state by creating a new object based on the previous state and updating the specific field (name, email, or message) with the new value.

Add a Success Message

Contrary to the static and stateless method in which Netlify redirects the page, for a stateful component to avoid redirecting errors (i.e., 404 messages), we create the handleSubmit function initiated when the form is filled out and submitted. It prevents the default form submission behavior and uses the Fetch API to send a POST request to the server. It sends the form data encoded as URL parameters and sets the form-name parameter to 'contact'. If the request is successful, an alert with ‘Success!’ is shown; otherwise, an error alert is shown. -

Conclusion

Mastering the art of creating a dynamic contact form can greatly enhance your web development skills. The seamless integration of Next.js and Netlify Forms not only streamlines the process but also empowers you to easily build interactive and user-friendly contact forms. By harnessing the power of server-side rendering, Stateless, and Stateful components and leveraging the simplicity of Netlify Forms, you can offer visitors to your website a smooth and engaging communication channel. So, dive into Next.js and Netlify Forms and unlock a realm of possibilities to craft modern and effective web solutions that leave a lasting impression. Resources

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay