Learning React Forms with Netlify


To follow this tutorial, you should be familiar with JavaScript to an intermediate level and already have worked with React. You probably don’t need to be using Gatsby to follow this tutorial, however, I mention it here because I will be basing this tutorial on the Gatsby starter project. I also assume that you will have used Netlify and (ideally) have already deployed a site, since this is out of the scope of this tutorial. If you are not using Netlify but simply want to learn the basics of using forms in React, this tutorial will still have you covered!

Fundamentals of Forms in React Hooks

To create a form in React, we will want to use component state to store the user inputs from our field. This is done so that we can track the updates that users make to the fields, making it easier to work with the data directly in JavaScript. We will need to set the values of our form by using a callback function. Every input tag in JSX has an onChange attribute that we can assign a callback function to, which gets triggered when the user makes a change to the given field. The event object passed to our onChange callback function has a target attribute, with holds both the name of the field as well as the new value. This makes it practical to use attribute names for our form state object that correlate with the names that we assign in our JSX input tags, since this makes it easy to update all our fields within a single function.

import React, { useState } from "react"

import Layout from "../components/layout"

const initFormState = {
  email: "",
  name: "",
}

const IndexPage = () => {
  const [formValues, setFormValues] = useState({
    ...initFormState,
  })
  const handleFormChange = e => {
    const changedElement = e.target
    const { name, value } = changedElement
    setFormValues({
      ...formValues,
      [name]: value,
    })
  }
  return (
    <Layout>
      <h1>Example Form</h1>
      <form>
        <input
          value={formValues.email}
          className="input-field"
          id="form-email"
          type="email"
          name="email"
          placeholder="example@mail.com"
          onChange={handleFormChange}
        />
        <input
          value={formValues.name}
          className="input-field"
          id="form-name"
          type="text"
          name="name"
          placeholder="John Doe"
          onChange={handleFormChange}
        />
        <input type="submit" name="submit-btn" value="Submit" />
      </form>
    </Layout>
  )
}

export default IndexPage
View after adding our form to the Gatsby default starter project

Adding Netlify specific Fields to add Form Functionality

Here is the code that we need to add to make our form compatible with Netlify’s forms feature:

return(
<form action="/page-2/" name="my-form" method="post" data-netlify="true">
      <input type="hidden" name="form-name" value="my-form">
        ...
</form>)

As you can see, we have added several new attributes to our form tag. The data-netlify attribute is used to allow Netlify to identify this form. You will also want to give it a name attribute, to define how the form will be named in your Netlify dashboard. Finally, you want to set the method to “post”, since that is the request method used to submit forms on Netlify. Optionally, you can set the action attribute to a url that you want the user to be redirected to after they submit the form – keep in mind that this is not like a regular form, where setting the action will have an impact on where the form data is sent (Netlify takes care of this internally). Since you are rendering your site with JavaScript, you will need to help Netlify identify which form is being submitted. You do this by creating a hidden field with a name attribute set to “form-name” and setting the value for this field to the name of the form that the user is submitting. Make sure this value is unique, because otherwise Netlify will not be able to separate data coming from different forms on your site. Once all of this is done, you see that after uploading your source code, Netlify will show your form in the dashboard under “forms”.

Submitting a Form asynchronously

As you may be able to tell if you have submitted a form, everything should work and you should be able to see the data that users submitted when you go on the view for the respective form. However, you might also notice that currently our entire site reloads whenever we make a submission – this is not great. A simple way to fix this, would be to create a new callback that we can use to overwrite the default submission event. This callback also gets an event object passed as a parameter, which we can use to stop the form from being submitted (we do this by calling the preventDefault method that you see in the following code). Within this callback, we can create an asynchronous fetch request to send our data to Netlify (remember: it needs to be of method “POST”). Afterwards, we will use the Gatsby navigate method to redirect the user to the new view if the submission was successful, without reloading the entire page (in true single page fashion).

... 
  const handleSubmit = e => {
    e.preventDefault()
    const form = e.target
    fetch("/", {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: encode({
        "form-name": form.getAttribute("name"),
        ...formValues,
      }),
    })
      .then(() => navigate(form.getAttribute("action")))
      .catch(error => alert(error))
  }
  return (
    <Layout>
      <h1>Example Form</h1>
      <form
        action="/page-2/"
        name="my-form"
        method="post"
        data-netlify="true"
        onSubmit={handleSubmit}
      >
      ...
      </form>
      ...)

Notice how we retrieve values that we assigned as attributes for our form tag, using the target object within the event that is passed to our submit callback – just like in the handleChange method!

Creating a Honeypot Field

Netlify offers a simple measure that can help against potential spam bots – a honeypot field. The idea is simple – if this hidden field is filled out, then the submission is discarded (since a normal user would not try to fill in a hidden field and it is therefore assumed that the submission was made by a spam bot). For this to work, we need to add an attribute named data-netlify-honeypot to our form tag as well as the actual hidden field itself. The value of the data-netlify-honeypot attribute needs to correlate with the name that we assign to our hidden bot field.

return(
<form
     ....
     data-netlify-honeypot="bot-field" />
     <input type="hidden" name="bot-field" />
     ...
</form>)

Next Steps

Congrats – you now have a working form that is collecting real user data! But what next? Netlify has the option to add webhooks that you can trigger when a user submits a form, which can be really useful. For example, for my mailing list, I use Zapier to add a user as a recipient to a newsletter in MailChimp. I like this method because it is very easy to set up and completely free! Another thing you might want to add is a Recaptcha that can help verify, with greater certainty than the honeypot field, whether a user is a spam bot or not.

Newsletter
Please enter a valid email!
Please agree to the terms!