How to use EmailJS for a Contact Us page
Tags: emailjs, reacthookform, typescript, react
Published: 2023-05-07 20:16:46

I remember some time ago while working on a side project. I was to implement a simple contact us page as part of the project. Initially, I used Google Firebase to store the responses. Then, I found **EmailJS** and it was so simple to use and very efficient.

In this article, you will learn how to set up a EmailJS account and integrate it into your ReactJS/NextJS application.

First, let’s start by creating a new React Project using Vite.
Open your VSCode or any other code editor, open the terminal and type in:
`yarn create vite` or `npm create vite@latest` then follow the prompts. I will be using React with Typescript in this example.

You can checkout [the official vite website](https://vitejs.dev/guide/) for more information on Vite.

Next, let’s install some dependencies. In your terminal, type in `yarn add @emailjs/browser react-hook-form`. Then run `yarn dev` to start the project.
You can get more info on [react-hook-form here](https://react-hook-form.com/get-started/)

I will delete some default files in the directory and change some styles as seen below.

![Project directory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4beoelzcbi8nj759btr.png)

Next, in my App.tsx, I will put up a basic contact us form.

```
import styles from "./app.module.css";
import { useForm } from "react-hook-form";
import { useState } from "react";

interface IFormInput {
  firstName: string;
  lastName: string;
  email: string;
  phone: string;
  message: string;
}
function App() {
  const [loading, setLoading] = useState(false);

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm<IFormInput>();
  const onSubmit = async (data: IFormInput) => {
    console.log(data);
  };

  return (
    <div className={styles.contact_form}>
      <h1>Contact Form</h1>
      <p>Our friendly team would love to hear from you.</p>

      <form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
        <div className={styles.group}>
          <div className={styles.input_group}>
            <label htmlFor="firstName">First Name</label>
            <input
              type="text"
              {...register("firstName", { required: true })}
              placeholder="Enter your first name"
            />
            {errors.firstName && (
              <span className={styles.error}>This field is required</span>
            )}
          </div>
          <div className={styles.input_group}>
            <label htmlFor="lastName">Last Name</label>
            <input
              type="text"
              {...register("lastName", { required: true })}
              placeholder="Enter your last name"
            />
            {errors.lastName && (
              <span className={styles.error}>This field is required</span>
            )}
          </div>
        </div>
        <div className={styles.input_group}>
          <label htmlFor="email">Email Address</label>
          <input
            type="email"
            {...register("email", { required: true })}
            placeholder="Enter your email address"
          />
          {errors.email && (
            <span className={styles.error}>This field is required</span>
          )}
        </div>
        <div className={styles.input_group}>
          <label htmlFor="phone">Phone Number</label>
          <input
            type="tel"
            {...register("phone", { required: true })}
            placeholder="+2348123456789"
          />
          {errors.phone && (
            <span className={styles.error}>This field is required</span>
          )}
        </div>
        <div className={styles.input_group}>
          <label htmlFor="message">Message</label>
          <textarea
            {...register("message", { required: true })}
            placeholder="Leave us a message..."
          />
          {errors.message && (
            <span className={styles.error}>This field is required</span>
          )}
        </div>

        <button disabled={loading} className={styles.button} type="submit">
          {loading ? "Sending..." : "Send Message"}
        </button>
      </form>
    </div>
  );
}

export default App;
```

In the code snippet above, I’m using CSS module for my component alongside react-hook-form for my form validation. I declared a loading state set to false by default.

Next, I want to go to [the official EmailJS website](https://www.emailjs.com/) and signup for a free account. The signup is straightforward.

![EmailJS website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aq0zzvj9hgt9j2rmb7iw.png)

Next, I will sign in to my account and setup a new email service. For this example, we will use only Gmail. On your dashboard, select **Add New Service** and select **Gmail**. Then select **Connect Service**. This will take you to your Gmail account to link together with Emailjs. Once done, select **Create Service**.


![Add New Service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4prun37s7rk684wbvpyi.png)

![Gmail Service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p6r2p9pgiychaqvq0k0s.png)

![Connect and Create Service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kqdzf9j87csnygktby38.png)

Next, we need to create an Email Template. On your dashboard, select **Email Templates** and select **Create New Template**. For the free version, you can only create 2 Email Templates.

![New Template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlkte646tgwvhlf9fakb.png)

You can configure your Email Template as you want.

![Configure Template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9hmrruajc7hk4d60qha.png)

In the image above, template body corresponds with the payload I’m sending from my app. You should also specify the receiver email and you can add extra Bcc and CC.

Next, we need to get 3 important credentials. The service ID, the template ID and your public key.

To get the template ID, navigate to the settings tab of the template and you will find the template key. You can as well modify the template name here.

![Template ID](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yf1q0adla8gcw1hy50fo.png)

Next, go to the **Email Services** screen and you will find the service ID for the service we connected earlier.

![Service ID](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3tnw0e0fvgrk0rytlpqz.png)

Next, go to **Account** and under the General tab, you will find your public and private keys. We only need the public key.

![Public and Private key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5z0yh08h28r3v4uupwa.png)

Lastly, we go back to our code and update our onSubmit function and integrate emailjs into our code.
To do this, in your App.tsx, `import emailjs from "@emailjs/browser";`

Then modify your onSubmit function as follow:

![onSubmit Function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khfc2oqhmfdpyt4ceq06.png)

Finally, your App.tsx should look like this:

```
import styles from "./app.module.css";
import { useForm } from "react-hook-form";
import { useState } from "react";
import emailjs from "@emailjs/browser";

interface IFormInput {
  firstName: string;
  lastName: string;
  email: string;
  phone: string;
  message: string;
}
function App() {
  const [loading, setLoading] = useState(false);

  const {
    register,
    handleSubmit,
    reset,
    formState: { errors },
  } = useForm<IFormInput>();
  const onSubmit = (data: IFormInput) => {
    setLoading(true);

    const templateParams = {
      ...data,
    };

    emailjs
      .send(
        "your_service_id",
        "your_template_id",
        templateParams,
        "your_public_key"
      )
      .then(() => {
        reset();
        setLoading(false);
        alert("One of our agents will contact you soon!");
      });
  };

  return (
    <div className={styles.contact_form}>
      <h1>Contact Form</h1>
      <p>Our friendly team would love to hear from you.</p>

      <form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
        <div className={styles.group}>
          <div className={styles.input_group}>
            <label htmlFor="firstName">First Name</label>
            <input
              type="text"
              {...register("firstName", { required: true })}
              placeholder="Enter your first name"
            />
            {errors.firstName && (
              <span className={styles.error}>This field is required</span>
            )}
          </div>
          <div className={styles.input_group}>
            <label htmlFor="lastName">Last Name</label>
            <input
              type="text"
              {...register("lastName", { required: true })}
              placeholder="Enter your last name"
            />
            {errors.lastName && (
              <span className={styles.error}>This field is required</span>
            )}
          </div>
        </div>
        <div className={styles.input_group}>
          <label htmlFor="email">Email Address</label>
          <input
            type="email"
            {...register("email", { required: true })}
            placeholder="Enter your email address"
          />
          {errors.email && (
            <span className={styles.error}>This field is required</span>
          )}
        </div>
        <div className={styles.input_group}>
          <label htmlFor="phone">Phone Number</label>
          <input
            type="tel"
            {...register("phone", { required: true })}
            placeholder="+2348123456789"
          />
          {errors.phone && (
            <span className={styles.error}>This field is required</span>
          )}
        </div>
        <div className={styles.input_group}>
          <label htmlFor="message">Message</label>
          <textarea
            {...register("message", { required: true })}
            placeholder="Leave us a message..."
          />
          {errors.message && (
            <span className={styles.error}>This field is required</span>
          )}
        </div>

        <button disabled={loading} className={styles.button} type="submit">
          {loading ? "Sending..." : "Send Message"}
        </button>
      </form>
    </div>
  );
}

export default App;
```

And that is it. You can now get new contact us messages directly in the receiver email you specified.


Thank you for reading. If this was helpful, leave a like.