Setting up a Serverless Contact form in React - using Nodemailer and Express
Tags: serverless, javascript, node, contact
Published: 2019-01-26 05:01:36

Having a contact form always works better than just displaying an email address on our website. A contact form gives our visitors an easy way to get in touch with us. In this post, we will go through a simple way to set up our own in [React](https://reactjs.org) using [Nodemailer](https://nodemailer.com) and [Express](https://expressjs.com) API. This post will also walk us through deploying it serverless with [Zeit](https://zeit.co/now) Now.


## What this app will do
By the end of this tutorial, you will have a contact form on your website that will bring the message straight to your inbox.

![Gif from Giphy](https://media.giphy.com/media/uWWmad9OgSckniKnEd/giphy.gif)
<figcaption>GIF from <a href="https://giphy.com/">Giphy</a></figcaption>

## Tools this app will use
+ [GitHub](https://github.com) — (for hosting code also required to deploy with Zeit later)
+ [Npm](https://npmjs.com) — (for using JS packages like create-react-app)
+ [Node JS](https://nodejs.org) and [Express JS](https://expressjs.com) (as our API will be built in Express)
+ [React JS](https://reactjs.org) (create-react-app for bootstrapping a standard React application and setting up our form)
+ [Axios](https://github.com/axios/axios) (for submission of form data to our remote API)
+ [Zeit Now](https://zeit.co/now) (to deploy our app serverless)

## Steps

## 1.Getting Things Ready
__GitHub Repos:__ — We start by creating two [GitHub](https://github.com) repos, one to host our React form and another for Node API. We could also do it in a single repo, but we are using two for better maintainability.

__Node & npm__ — Download the latest version of node.js from the [link](https://nodejs.org/en). In this post we are using version 11.7.0. Node comes with npm. To make sure node and npm are installed, check their versions using the following commands on the terminal:

```
//for node
node -v

//for npm
npm -v
```

__React__ — We’re using create-react-app for our React application where we will build our form. Install create-react-app globally and generate our React app using the following commands:

```
//Install create-react-app globally
npm install create-react-app -g

//Generate a new react app called my-app
create-react-app my-app
cd my-app
npm start
```

## 2.The Form

Let’s get started with setting up a component that returns an HTML form. We’re using [Bootstrap](https://getbootstrap.com) classes for style in the code below, so they are optional You can use your own CSS classes as well.

{% gist https://gist.github.com/gmrsagar/79170d97415737f94d343ea04fca3b3b %}

Here, each input has an _onChange_ handler corresponding to a specific variable in our component’s state. So, when the input changes, the state gets updated as well. The form itself has an _onSubmit_ handler that calls the _formSubmit_ function which handles our API calls.

We will have a look at the function, but before that, let’s install axios (which we will be using in the function) to make HTTP request to the API.

```
//Install axios
npm install axios --save
```

Setting up our component src/App.js:

{% gist https://gist.github.com/gmrsagar/ce071f639f2f3deb703075c690b410de %}

Now, we add the functions to handle form submission in our component.

{% gist https://gist.github.com/gmrsagar/5c45a2552df28ffdcd61ed3387761286 %}

The _preventDefault()_ function (on line 2), as the name suggests, prevents the default action of the form, which would’ve caused a page reload. While the message is being sent, the button text changes to “…Sending”, and axios makes the API call.

_Note: “API_URI”(line 14) is the uri of the endpoint of our API which will be discussed in the deployment section of this post(Step 4)._

If everything goes right, the resetForm is called, which we haven’t defined yet. So let’s define the reset function that will reset our form fields and update our button label:

{% gist https://gist.github.com/gmrsagar/662704b4fbf80e9ea4b5a95b545e4695 %}

## 3.API

Now, we need something to transport our form inputs to the API, so we set up the nodemailer, config file and route. But before that, we need to setup [Express.js](https://expressjs.com) in our Node API repo:

```
//Initialize
npm init

//Install express and other dependencies
npm install express body-parser nodemailer cors --save
```

Now we need to make a small change in our package.json file. Find “scripts” and add the following “start” line to it:

```
"scripts": {
  "start": "node ."
}
```

Now, in our directory we create an index.js file with the following code:

{% gist https://gist.github.com/gmrsagar/bbca178c415d620c8106ebd7f0a86bfc %}

> __Important Note:__ Since we are working on the development version, the credentials will be exposed on GitHub, so make sure your repo is private or use a test email address for development version. Later in production, you can make use of the Zeit environment variables to store credentials safely.

We have installed body-parser to process the form data, and CORS to allow cross-origin requests.

We have setup a Nodemailer SMTP Transport and our route that will receive the data from our React form and send an email to the destination email address that we specify.

## 4.Deploy

Finally! with all that done it’s time to deploy our app. We’re using Zeit Now for deployment, you can choose any other service that you like.

![Dexter](https://media.giphy.com/media/zLrMT1J1RuJ9u/giphy.gif)
<figcaption>GIF from <a href="https://giphy.com">Giphy</a></figcaption>

Start by creating an account on [Zeit](https://zeit.co). Login and head over to “Now” from the top navigation. Connect your GitHub account and add the two repos that we just created. Now, we go back to our code and add an empty now.json file in both the repos.

It’s now time to push our codes to the respective github repos.

Now we create a new branch in both repos and work with those because we will need to create Pull Request for Zeit now to run deployment.

```
//create and change to new branch
git checkout -b new-branch
```

Now we add some content to the now.json files.
For our React repo we will use the following content on our now.json:

{% gist https://gist.github.com/gmrsagar/1afe89f363e470215bacd548b6c628fd %}

For our Node repo, we will use the following content on now.json:

{% gist https://gist.github.com/gmrsagar/4c1821c1a6527ed3f64273e55f2be349 %}

_Note: More examples for Zeit Now configurations can be found [here](https://github.com/zeit/now-examples)._

Finally, we make a small change in our package.json in our React repo. 
Find “scripts” and add the “now-build” line to it:

```
    "scripts": {
        ...
        "now-build": "react-scripts build && mv build dist"
    }
```

Now, we push the codes to their respective Github repos(new-branch) and then create a Pull Request in each. Zeit Now will immediately deploy the app recognizing the now.json files. You can view the app URL by clicking “Show all checks” and then “details” in the Pull Request summary. Lastly, __be sure to copy the link and replace API_URI in the App.js file in React app.__ Now our form should successfully deliver emails.

_Thanks for reading!_
_Happy Coding!_