Building a React Contact Form Without a Backend

Quickly creating a contact form on your site to let your audience get in touch with you can be anything but quick. This is especially true if you don’t have a backend in place, or you don’t have control over the backend. Yet, we can get up and running fairly quickly with third-party solutions, without the need for a backend. In this tutorial, we will do just that. We will utilize a third-party service for sending emails.

Learn React with Udemy

What is Needed for a Contact Form Without a Backend?

Apart from React itself, we will be using EmailJS as a third-party service for sending emails right from our React component. The service has a free plan for up to 200 monthly requests, and it integrates nicely with multiple services. In this tutorial, we will connect it to a Gmail account, but you can use any of the following services:

The list of available services on EmailJS

Setting Up a Contact Component

To start out, let’s set up the component that we will use to send emails. Create a new component in your React app called contact.js, and add the following layout:

import React, { useState } from 'react'

const Contact = () => {
    return (
        <div id="contact-form">
            <input type="text" placeholder="Your Name" />
            <input type="email" placeholder="Your email address" />
            <textarea placeholder="Your message"></textarea>
            <button>Send Message</button>
            <span>Thank you for your message, we will be in touch in no time!</span>
        </div>
    );
};

export default Contact;
contact.js
Copied to clipboard!

Make sure you import useState from React, as we will need to use it for the input fields. Not much going on at the moment. We have some input fields and a button for sending an email. To store the state of each input, we can introduce a useState for each of the fields:

const Contact = () => {
    const [name, setName] = useState('');
    const [email, setEmail] = useState('');
    const [message, setMessage] = useState('');
    const [emailSent, setEmailSent] = useState(false);

    return (
        <input type="text" placeholder="Your Name" value={name} onChange={e => setName(e.target.value)} />
        <input type="email" placeholder="Your email address" value={email} onChange={e => setEmail(e.target.value)} />
        <textarea placeholder="Your message" value={message} onChange={e => setMessage(e.target.value)}></textarea>
        <button onClick={submit}>Send Message</button>
        <span className={emailSent ? 'visible' : null}>Thank you for your message, we will be in touch in no time!</span>
    );
};
contact.js
Copied to clipboard!

We will need to assign the first value of the useState to the input, and add an onChange event listener for updating the state. Make sure you only pass the value of the input to the set function that you can reach through e.target.value.

Having confusions on how React hooks work? Make sure you give a go for the tutorial below:

All You Need to Know About React Hooks

We also have an emailSent flag for verifying if the email has been sent. We can use this flag to show and hide a thank you message at the end of the form. Note that we have also added an onClick callback for the button in the code example. This will call the submit function that we’ve yet to define above our return statement:

const submit = () => {
    if (name && email && message) {
       // TODO - send mail

        setName('');
        setEmail('');
        setMessage('');
        setEmailSent(true);
    } else {
        alert('Please fill in all fields.');
    }
}

return ( ... );
contact.js
Copied to clipboard!

We only want to send an email when all of the fields are filled out. Of course, this basic example doesn’t cater to invalid emails. For that, we can use the following function to validate the input:

const isValidEmail = email => {
    const regex = /^(([^<>()\[\]\\.,;:\[email protected]"]+(\.[^<>()\[\]\\.,;:\[email protected]"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return regex.test(String(email).toLowerCase());
};
contact.js
Copied to clipboard!

It uses regular expressions to only allow valid email addresses. If one of the fields is empty, we can alert the user about it in the else branch. This is where you can also implement showing toast messages or other types of feedback to the user. We can also empty the input field once the email is sent, and set the emailSent flag to true.


Setting Up EmailJS

The last step that remained is to actually hook up EmailJS with our component, so we can send out the messages. Head over to emailjs.com and create a new account if you haven’t already, then log into your dashboard, and add a new service. As mentioned in the beginning. I’m using Gmail throughout this tutorial.

If you also choose to use Gmail, make sure you allow “Send email on your behalf” on the authentication page when you connect your Gmail account to EmailJS. After creating the service, you will receive a service ID. We will need this to send emails through React.

Setting up Gmail as a service in EmailJS

Now head over to the “Email Templates” tab on your dashboard, and create a new template as well. This will be the template that is used when you receive new emails from the contact form:

The template format in EmailJS

As you can see, we can use the {{name}} notation in order to insert template parameters. We want to name the variables the same way we have inside this template. In the settings tab under the template, you’ll be able to find a template ID. Make sure you save this as we will need this as well.

Lastly, we also need the userID, so the request to EmailJS can be authenticated. To get the userID, head over to the “Integration” panel, and copy the ID only.


Connecting EmailJS

Now that we have everything set up, we can finally connect EmailJS to our React component. But first, we will need to install the SDK as a dependency:

npm i emailjs-com

Then import it into our React component, and call emailjs.send inside the submit function, to send an email with the template parameters that we have defined:

import emailjs from 'emailjs-com'

const Contact = () => {
    ...
   
    const submit = () => {
        if (name && email && message) {
            const serviceId = 'service_id';
            const templateId = 'template_id';
            const userId = 'user_id';
            const templateParams = {
                name,
                email,
                message
            };

            emailjs.send(serviceId, templateId, templateParams, userId)
                .then(response => console.log(response))
                .then(error => console.log(error));

            setName('');
            setEmail('');
            setMessage('');
            setEmailSent(true);
        } else {
            alert('Please fill in all fields.');
        }
    }
}
contact.jsMake sure you give the same name to the variables, you did in the template.
Copied to clipboard!

As you can see, it takes in four different parameters: the ID of the service we have created, as well as the template’s ID, the account’s ID, and the parameters that need to be resolved inside the template. The send method returns a Promise, so we can chain then callbacks from them, or if you prefer, we can also use async/await.

It’s also good to note that if you use the init function to init the SDK, you don’t have to pass the userId to the send method:

import { init } from 'emailjs-com';
init('user_id');
contact.jsIf emailJS is inited first, no user ID is required for the send method.
Copied to clipboard!

Summary

If you hit the send button now, you should be able to receive an email a couple of seconds later with the data you have provided in the form. Overall, emailJS makes it easy and quick to set up a contact form inside a React application, or for that matter, in any JavaScript application without the need of a backend.

Learn React with Udemy

You can find additional documentation on the SDK on their official website. If you would like to get the source code in one piece that is used for this project, you can clone it from GitHub. Thank you for reading through, happy coding!

📚 Get access to exclusive content

Want to get access to exclusive content? Support webtips to get access to tips, checklists, cheatsheets, and much more. ☕

Get access Support us
Read more on
🎉 Thank you for subscribing to our newsletter. x