{"id":353128,"date":"2021-10-21T07:26:03","date_gmt":"2021-10-21T14:26:03","guid":{"rendered":"https:\/\/css-tricks.com\/?p=353128"},"modified":"2021-10-21T07:26:06","modified_gmt":"2021-10-21T14:26:06","slug":"how-to-create-a-contact-form-with-next-js-and-netlify","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/how-to-create-a-contact-form-with-next-js-and-netlify\/","title":{"rendered":"How to Create a Contact Form With Next.js and Netlify"},"content":{"rendered":"\n

We’re going to create a contact form with Next.js and Netlify that displays a confirmation screen and features enhanced spam detection.<\/p>\n\n\n\n

Next.js is a powerful React framework for developing performant React applications that scale. By integrating a Next.js site with Netlify\u2019s technology, we can quickly get a working contact form up and running without having to write any server-side code.<\/p>\n\n\n\n

Not only is it a relatively fast process to set up forms to be processed by Netlify, but it\u2019s also free to get started (with up to 100 free submissions\/per site hosted on Netlify). Form submissions automatically go through Netlify\u2019s built-in spam filter which uses Akismet and there are also options that can be configured to increase the level of spam detection.<\/p>\n\n\n\n\n\n\n\n

\"\"<\/figure>\n\n\n

Creating the contact form<\/h3>\n\n\n

Within the Next.js application we should create a ContactForm<\/code> component to render the contact form inside of the contact page. If you\u2019d like for this form to render at \/contact<\/code>, then the ContactForm<\/code> component below with labels and input fields should be used within the pages\/contact.js<\/code> file.<\/p>\n\n\n\n

const ContactForm = (\n  <form\n    name=\"contact-form\"\n    method=\"POST\"\n    action=\"contact\/?success=true\"\n  >\n    <label htmlFor=\"name\">Name *<\/label>\n    <input\n      id=\"name\"\n      name=\"name\"\n      required\n      type=\"text\"\n    \/>\n    <label htmlFor=\"company\">Company *<\/label>\n    <input id=\"company\" name=\"company\" required type=\"text\" \/>\n    <label htmlFor=\"email\">E-mail Address *<\/label>\n    <input id=\"email\" type=\"email\" name=\"email\" required \/>\n    <label htmlFor=\"message\">Message *<\/label>\n    <textarea id=\"message\" name=\"message\" required><\/textarea>\n    <button type=\"submit\">Submit<\/button>\n  <\/form>\n);<\/code><\/pre>\n\n\n\n

The above markup is required to render a form with a field for Name, Company, Email address and message with a submit button. When submitting the form, based on the value of the form\u2019s action, it should redirect to contact\/?success=true<\/code> from \/contact<\/code>. Right now there is not yet a difference between the page\u2019s appearance with and without the success query parameter, but we will update that later.<\/p>\n\n\n\n

Our Contact.js<\/code> file looks like this so far:<\/p>\n\n\n\n

import React from \"react\";\nconst ContactPage = () => {\n const ContactForm = (\/* code in above code sample*\/)\n \n return (\n   <div>\n     <h1>Contact Us<\/h1>\n     {ContactForm}\n   <\/div>\n );\n};\n \nexport default ContactPage;<\/code><\/pre>\n\n\n\n

Now that we have the basic form set up, the real magic will happen after we add additional information for Netlify to auto-recognize the form during future site deployments. To accomplish this we should update the form to have the attribute data-netlify=\"true\"<\/code> and a hidden input field that contains the name of our contact form. In Netlify, once we navigate to our site in the dashboard and then click on the \u201cforms\u201d tab  we will be able to view our form responses based on the name that we\u2019ve put in our hidden field. It\u2019s important that if you have multiple forms within a site that they have unique names so that they are recorded properly in Netlify.<\/p>\n\n\n\n

<form\n  method=\"POST\"\n  name=\"contact-form\"\n  action=\"contact\/?success=true\"\n  data-netlify=\"true\"\n>\n<input type=\"hidden\" name=\"form-name\" value=\"contact-form\" \/><\/code><\/pre>\n\n\n\n

After successfully deploying the site to Netlify with the data-netlify<\/code> attribute and the form-name<\/code> field  then we can go to the deployed version of the site and fill out the form. Upon submitting the form and navigating to https:\/\/app.netlify.com\/sites\/site-name\/forms<\/code> (where site-name<\/code> is the name of your site) then our most recent form submission should appear if we have successfully set up the form. <\/p>\n\n\n\n

\"\"<\/figure>\n\n\n

Redirect to confirmation screen <\/h3>\n\n\n

In order to improve the user experience, we should add some logic to redirect to a confirmation screen on form submission when the URL changes to \/contact\/?success=true<\/code>. There is also the option to redirect to an entirely different page as the action when the form is submitted but using query params we can achieve something similar with the Next Router. We can accomplish this by creating a new variable to determine if the confirmation screen or the form should be visible based on the query parameter. The next\/router which is imported with import { useRouter } from \"next\/router\";<\/code> can be used to retrieve the current query params. <\/p>\n\n\n\n

const router = useRouter();  \nconst confirmationScreenVisible = router.query?.success && router.query.success === \"true\";<\/code><\/pre>\n\n\n\n

In our case, the confirmation screen and form can never be visible at the same time; therefore, the following statement can be used to determine if the form is visible or not.<\/p>\n\n\n\n

const formVisible = !confirmationScreenVisible; <\/code><\/pre>\n\n\n\n

To give users the option to resubmit the form, we can add a button to the confirmation screen to reset the form by clearing the query params. Using router.replace<\/code> (instead of router.push<\/code>) not only updates the page but replaces the current page in the history to the version without query params. <\/p>\n\n\n\n

<button onClick={() => router.replace(\"\/contact\", undefined, { shallow: true })}> Submit Another Response <\/button><\/code><\/pre>\n\n\n\n

We can then conditionally render the form based on whether or not the form is visible with:<\/p>\n\n\n\n

{formVisible ? ContactForm : ConfirmationMessage}<\/code><\/pre>\n\n\n\n

Putting it all together, we can use the following code to conditionally render the form based on the query params (which are updated when the form is submitted):<\/p>\n\n\n\n

import React, { useState } from \"react\";\nimport { useRouter } from \"next\/router\";\n \nconst ContactPage = () => {\n const [submitterName, setSubmitterName] = useState(\"\");\n const router = useRouter();\n const confirmationScreenVisible =\n   router.query?.success && router.query.success === \"true\";\n const formVisible = !confirmationScreenVisible;\n \n const ConfirmationMessage = (\n   <React.Fragment>\n     <p>\n       Thank you for submitting this form. Someone should get back to you within 24-48 hours.\n     <\/p>\n \n     <button onClick={() => router.replace(\"\/contact\", undefined, { shallow: true })}> Submit Another Response <\/button>\n   <\/React.Fragment>\n );\n \n const ContactForm = (\/* code in first code example *\/);\n \n return (\n   <div>\n     <h1>Contact Us<\/h1>\n{formVisible ? ContactForm : ConfirmationMessage}\n   <\/div>\n );\n};\n \nexport default ContactPage;<\/code><\/pre>\n\n\n

Adding a hidden bot field<\/h3>\n\n\n

Now that the core functionality of our form is working, we can add additional spam detection to our form in addition to the base spam detection because Akismet is included with all Netlify Forms by default. We can enable this by adding data-netlify-honeypot=\"bot-field\"<\/code> to our form.<\/p>\n\n\n\n

<form\n  className=\"container\"\n  method=\"POST\"\n  name=\"contact-form\"\n  action=\"contact\/?success=true\"\n  data-netlify=\"true\"\n  data-netlify-honeypot=\"bot-field\"\n><\/code><\/pre>\n\n\n\n

We also need to create a new hidden paragraph that contains a label named bot-field<\/code> that contains the input. This field is \u201cvisible\u201d to bots, but not humans. When this honeypot form field is filled, Netlify detects a bot and then the submission is flagged as spam.<\/p>\n\n\n\n

<p hidden>\n  <label>\n    Don\u2019t fill this out: <input name=\"bot-field\" \/>\n  <\/label>\n<\/p><\/code><\/pre>\n\n\n

Further customizations<\/h3>\n\n\n