Build a React Contact Form with Email Notifications in 5 Minutes
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
- A React project (Create React App, Vite, Next.js, React Router — anything)
- A free formto.email account
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:
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:
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:
- Create React App / Vite — Drop the component in
- Next.js — Works in both App Router and Pages Router (client component)
- React Router 7 — Works as a standard route component
- Remix — Use alongside Remix actions, or replace them entirely
- Astro — Use as a client:load island
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:
- More code to write and maintain. The formto.email approach is one component with no backend.
- Spam protection is on you. formto.email includes AI spam filtering out of the box.
- Email deliverability. Sending from your own domain/IP can land in spam. Dedicated email services have better deliverability infrastructure.
- You get a dashboard. View, search, and export all submissions from the formto.email dashboard — no need to build your own admin UI.
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.