How to Build a React Contact Form

Last updated: March 2026

Adding a contact form to a React app usually means setting up API routes, configuring email services, and handling server-side logic. With a form backend service, you skip all of that. This guide shows how to add a fully functional contact form to any React project in minutes.

How it works

Your React component renders an HTML form. On submit, the form data is sent to a FormWit endpoint via a standard POST request. FormWit processes the submission, filters spam, stores the data, and sends you an email notification. No Express server, no API routes, no email setup.

The flow looks like this:

  1. A visitor fills out your contact form in the browser
  2. Your React component sends the form data to your FormWit endpoint
  3. FormWit validates the data, checks for spam, and stores the submission
  4. You receive an email notification and can view the submission in your dashboard

Set up a React contact form

Step 1: Create a FormWit account

Go to app.formwit.com/auth/signup and create a free account. No credit card required. Once signed in, click Create Form and give it a name (e.g., "Contact Form"). You'll get a unique endpoint URL that looks like https://app.formwit.com/api/s/YOUR_FORM_ID.

Step 2: Create the contact form component

Create a new file called ContactForm.jsx in your React project. This component handles form submission via fetch, tracks the submission status with useState, and includes a honeypot field for spam protection.

import { useState } from 'react';

function ContactForm() {
  const [status, setStatus] = useState('idle');

  async function handleSubmit(e) {
    e.preventDefault();
    setStatus('sending');

    const form = e.target;
    const data = new FormData(form);

    try {
      const response = await fetch(form.action, {
        method: 'POST',
        body: data,
      });

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

  return (
    <form
      action="https://app.formwit.com/api/s/YOUR_FORM_ID"
      method="POST"
      onSubmit={handleSubmit}
    >
      <label htmlFor="name">Name</label>
      <input type="text" id="name" name="name" required />

      <label htmlFor="email">Email</label>
      <input type="email" id="email" name="email" required />

      <label htmlFor="message">Message</label>
      <textarea id="message" name="message" required></textarea>

      {/* Honeypot spam protection */}
      <input type="text" name="_gotcha" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" />

      <button type="submit" disabled={status === 'sending'}>
        {status === 'sending' ? 'Sending...' : 'Send Message'}
      </button>

      {status === 'success' && <p>Message sent successfully!</p>}
      {status === 'error' && <p>Something went wrong. Please try again.</p>}
    </form>
  );
}

export default ContactForm;

Replace YOUR_FORM_ID with the endpoint ID from your FormWit dashboard. The component uses FormData to serialize the form fields and sends them via fetch. The hidden _gotcha field is a honeypot. Bots fill it in, humans don't, so FormWit uses it to filter spam.

Step 3: Add the component to your app

Import and render the component wherever you want the contact form to appear:

import ContactForm from './ContactForm';

function ContactPage() {
  return (
    <div>
      <h1>Contact Us</h1>
      <ContactForm />
    </div>
  );
}

export default ContactPage;

Step 4: Test it

Run your React development server, fill out the form, and hit submit. You should see the success message appear in the browser. Check your FormWit dashboard (the submission will be listed there) and check your email for the notification.

Adding a custom redirect

If you want to redirect users to a thank-you page after submission instead of showing an inline message, add a hidden redirect_to field to your form:

<input type="hidden" name="redirect_to" value="https://yoursite.com/thank-you" />

This tells FormWit to redirect the browser to that URL after a successful submission. The redirect_to value must be a valid http or https URL. If you're handling submission via fetch (as in the component above), you'll need to handle the redirect in your JavaScript instead:

if (response.ok) {
  window.location.href = 'https://yoursite.com/thank-you';
}

Using with React frameworks

This approach works with any React setup:

  • Vite + React - works as shown above, no changes needed.
  • Create React App - same setup, drop the component into your src/ folder.
  • Next.js - add 'use client' at the top of your component file since it uses useState and event handlers. Works in both the App Router and Pages Router. See our Next.js contact form guide for more details.
  • Remix - use the component as a client-side form. No server action required.
  • Gatsby - works in any page or component file without modification.

Because the form submission goes directly from the browser to FormWit, no server-side code is needed regardless of which framework you use.

Summary

Adding a contact form to a React app doesn't require a backend server, API routes, or email configuration. With FormWit, you create a form endpoint, build a standard React component, and let the service handle spam filtering, data storage, and email notifications.

FormWit's free plan includes unlimited forms, 100 submissions per month, email notifications, and built-in spam protection. Create your free account and add a contact form to your React app in minutes.

Related guides: JavaScript contact form · Next.js contact form · Gatsby contact form · HTML contact form · Spam protection · Contact form templates

Frequently asked questions

Can I use FormWit with React?

Yes. Create a React component with a form, use useState for submission status, and send form data to your FormWit endpoint via fetch. The component works with Vite, Create React App, Next.js, Remix, and Gatsby without modification.

Do I need Redux or Zustand?

No. A contact form is local component state. React's built-in useState hook is all you need to track submission status (idle, sending, success, error). There is no reason to put contact form state in a global store.

Does it work with Create React App?

Yes. Drop the ContactForm.jsx component into your src/ folder and import it in any page. Create React App uses Vite or webpack under the hood, and FormWit is just a fetch POST to an external URL, so no special configuration is needed.

Want to skip the setup?

FormWit gives you a form endpoint in 60 seconds. Free plan, no credit card.

Create Free Form

Need a form fast?

Build one visually with our free HTML form generator — no coding required.

Try the Form Generator →

Add FormWit to your React app

Add a contact form to your site in 30 seconds. No backend code required.

Try FormWit Free