← Back to Blog
Developer Tutorial

Build a React Contact Form with Email Notifications in 5 Minutes

March 18, 2026 · 6 min read

You're building a React app and you need a contact form. The form needs to send submissions to your email. But you really don't want to spin up an Express server, configure Nodemailer, deploy an API route, and deal with email deliverability.

Good news: you don't have to. With formto.email, you can wire up a fully working React contact form with email notifications in about 5 minutes — with zero backend code.

Prerequisites

Step 1: Get Your Form Endpoint

Sign up at formto.email, create a form, and grab your endpoint URL. It looks like https://formto.email/f/abc123.

Step 2: Build the Contact Form Component

Here's a complete, production-ready React contact form component. It handles submission, loading state, success/error messages, and sends data to your email via formto.email:

ContactForm.jsx
import { useState } from 'react';

const FORM_ENDPOINT = 'https://formto.email/f/your-form-id';

export default function ContactForm() {
  const [status, setStatus] = useState('idle');
  // 'idle' | 'submitting' | 'success' | 'error'

  const handleSubmit = async (e) => {
    e.preventDefault();
    setStatus('submitting');

    try {
      const response = await fetch(FORM_ENDPOINT, {
        method: 'POST',
        body: new FormData(e.target),
        headers: { Accept: 'application/json' },
      });

      if (response.ok) {
        setStatus('success');
        e.target.reset();
      } else {
        setStatus('error');
      }
    } catch {
      setStatus('error');
    }
  };

  if (status === 'success') {
    return (
      <div className="success-message">
        <h3>Message sent!</h3>
        <p>Thanks for reaching out. We'll reply soon.</p>
        <button onClick={() => setStatus('idle')}>
          Send another message
        </button>
      </div>
    );
  }

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="name">Name</label>
      <input
        type="text" id="name" name="name"
        required placeholder="Your name"
      />

      <label htmlFor="email">Email</label>
      <input
        type="email" id="email" name="email"
        required placeholder="you@example.com"
      />

      <label htmlFor="message">Message</label>
      <textarea
        id="message" name="message"
        required placeholder="Your message..."
        rows={5}
      />

      {status === 'error' && (
        <p className="error">
          Something went wrong. Please try again.
        </p>
      )}

      <button
        type="submit"
        disabled={status === 'submitting'}
      >
        {status === 'submitting'
          ? 'Sending...'
          : 'Send Message'}
      </button>
    </form>
  );
}

Key detail: Setting the Accept: application/json header tells formto.email to return JSON instead of redirecting. This is what lets you handle the response in React and show inline success/error messages.

Step 3: Style It

The component above is unstyled so you can use whatever CSS approach you prefer — Tailwind, CSS modules, styled-components, plain CSS. The form is just standard HTML elements, so it works with any styling method.

Using with TypeScript

If you're using TypeScript, the component works as-is. The FormData constructor accepts the form element from e.target. If your linter complains, you can cast it:

TypeScript version
const handleSubmit = async (
  e: React.FormEvent<HTMLFormElement>
) => {
  e.preventDefault();
  const form = e.currentTarget;
  const data = new FormData(form);
  // ...rest of the logic
};

Works with Any React Framework

This approach works everywhere React runs:

Why Not Just Use an API Route?

If you're using Next.js or Remix, you could write an API route that sends email via Resend, SendGrid, etc. That works, but consider:

Add a working contact form to your React app in 5 minutes

No Express. No API routes. No email configuration. Just a form endpoint and a fetch call.

Get Your Free Endpoint →

Wrapping Up

Building a React contact form that sends to email doesn't require a backend, an email SDK, or server-side logic. With formto.email, you get a production-ready form endpoint with spam protection, email delivery, and a submissions dashboard — all from a single fetch call in your React component.

The free tier gives you 500 submissions per month, which is plenty for most projects. If you need more, Pro starts at $7/month with 10,000 submissions and file upload support.