Building a React Contact Form Without a Backend

Building a React Contact Form Without a Backend

Using EmailJS to send emails without backend
Ferenc AlmasiLast updated 2024 January 01 • Read time 10 min read • EmailJS v3.11
Learn how you can easily send emails in React without any backend using the free version of EmailJS.

Quickly creating a contact form on our site to let our audience get in touch with us 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'll do just that. We'll utilize a third-party service for sending emails.


What is Needed for a Contact Form Without a Backend

Apart from React itself, we'll 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 integrates nicely with multiple services. In this tutorial, we'll connect it to a Gmail account, but you can use any of the following services:

The list of available services on EmailJS
The list of available services on EmailJS

Setting Up the Contact Component

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

Copied to clipboard! Playground
import { useState } from 'react'

export const ContactForm = () => {
    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>
    )
}
ContactForm.tsx
Create the layout for the contact form

Make sure you import useState from React, as we'll need to use it for the input fields. Here 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:

Copied to clipboard! Playground
export const ContactForm = () => {
    const [name, setName] = useState('')
    const [email, setEmail] = useState('')
    const [message, setMessage] = useState('')
    const [emailSent, setEmailSent] = useState(false)

    return (
        <div id="contact-form">
            <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' : undefined}>
                Thank you for your message, we will be in touch in no time!
            </span>
        </div>
    )
}
ContactForm.tsx
Create the state for the component

We'll 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.

Are you new to React hooks? 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:

Copied to clipboard! Playground
const submit = () => {
    if (name && email && message) {
        // TODO - send mail

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

return ( ... )
ContactForm.tsx
Only send the form if all fields are filled

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 emails:

🚫 Refresh console

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 to show the thank you message.

Looking to improve your skills? Check out our interactive course to master React from start to finish.
Master Reactinfo Remove ads

Setting Up EmailJS

The last step that remains 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 using the "Email Services" tab. As mentioned in the beginning, we're 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'll receive a service ID. We'll need this to send emails through React.

Setting up Gmail as a service in EmailJS
Set up a service and save the service ID

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
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'll need this as well.

Lastly, we also need the public key so the request to EmailJS can be authenticated. To get the public key, head over to the “Account” tab and copy the value in the "Public Key" field.

You can find the full source code in one piece on Stackblitz.


Connecting EmailJS

Now that we have everything set up, we can finally connect EmailJS to our React component. But first, we'll need to install the SDK as a dependency. Enter the following into your terminal to install EmailJS:

Copied to clipboard!
npm i @emailjs/browser
Install EmailJS as a dependency

Next, we need to authenticate the SDK by calling the init function. If you're using contact forms in multiple places, you'll likely want to do this at the root of your component, such as in your App component:

Copied to clipboard! Playground
import { ContactForm } from './ContactForm'
import emailjs from '@emailjs/browser'

const App = () => {
    emailjs.init('publicKey')

    return (
        <ContactForm />
    )
}
App.tsx
Init the EmailJS SDK

Insert the public key you've copied from the dashboard into the init method. Now we can import the SDK into our ContactForm component and call emailjs.send inside the submit function to send an email with the template parameters that we have defined:

Copied to clipboard! Playground
import emailjs from '@emailjs/browser'

export const ContactForm = () => {
    ...
   
    const submit = () => {
        if (name && email && message) {
            const serviceId = 'service_id'
            const templateId = 'template_id'
            const templateParams = {
                name,
                email,
                message
            }

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

            setName('');
            setEmail('');
            setMessage('');
            setEmailSent(true);
        } else {
            alert('Please fill in all fields.');
        }
    }
}
ContactForm.tsx
Make sure you give the same name to the variables, you did in the template

As we can see, it takes in three different parameters:

  • serviceId: The ID of the service we have created on the "Email Services" tab.
  • templateId: The ID of the template we have created using the "Email Templates" tab.
  • templateParams: The list of parameters that need to be resolved inside the template. The variables must match the keys defined inside the template on EmailJS.

The send method returns a Promise, so we can chain then callbacks or we can also use async/await. When testing the sending functionality, make sure to keep an eye on the console, as EmailJS provides helpful error messages in case something goes wrong:

Copied to clipboard!
{status: 400, text: 'The Public Key is invalid...' }
{status: 400, text: 'The template ID is invalid...' }
Error responses from EmailJS

Summary

If we click on the send button now, we should be able to receive an email a couple of seconds later with the data we 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 for a backend.

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 find it on Stackblitz. Thank you for reading through, happy coding!

Did you find this page helpful?
📚 More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access 100+ interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Prepare for technical interviews
Become a Pro

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.