React Contact Form
A ready-to-use React component that handles form submission with useState for state management and fetch for AJAX submission. Includes loading state, success message, and error handling. Drop it into any React or Next.js project. For a full walkthrough, see the React contact form guide.
Template Code
import { useState } from 'react';
function ContactForm() {
const [status, setStatus] = useState('idle'); // idle | sending | success | error
async function handleSubmit(e) {
e.preventDefault();
setStatus('sending');
const form = e.target;
const data = new FormData(form);
try {
const res = await fetch(form.action, { method: 'POST', body: data });
if (res.ok) {
setStatus('success');
form.reset();
} else {
setStatus('error');
}
} catch {
setStatus('error');
}
}
if (status === 'success') {
return <p style={{ color: '#16a34a', fontWeight: 600 }}>Message sent! We'll be in touch.</p>;
}
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 />
{/* 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 === 'error' && <p style={{ color: '#dc2626' }}>Something went wrong. Please try again.</p>}
</form>
);
}
export default ContactForm; Want to customize?
Build your own form visually with our free HTML form generator.
Try the Form Generator →Use cases
- React single-page applications
- Next.js static or server-rendered sites
- React-based portfolios and landing pages
- Modal or dialog contact forms in React apps
Customization tips
- Add your own CSS classes or use a UI library like Tailwind, Chakra UI, or Material UI for styling
- Add client-side validation with
patternattributes or a library like Zod - Convert to TypeScript by adding type annotations to the event parameter and state
- Use
useRefinstead ofe.targetif you need to access the form outside the handler
Related guide
Want a step-by-step walkthrough? Read the full React Contact Form Guide.
Related templates
AJAX Contact Form (No Page Reload)
Submit the form via JavaScript without a page reload. Shows a success message inline.
Vue 3 Contact Form
A Vue 3 contact form component using the Composition API. Handles submission, loading, and success/error states with ref().
Basic Contact Form
A minimal HTML contact form with name, email, and message fields. Works on any website with no CSS framework required.
Frequently asked questions
Does this work with Next.js?
"use client" at the top of the file for Next.js App Router. It works with both Pages Router and App Router. Can I use this with TypeScript?
React.FormEvent<HTMLFormElement> and the status state as a union type: 'idle' | 'sending' | 'success' | 'error'. How do I add form validation?
required, type="email") work out of the box. For custom validation, check field values in handleSubmit before calling fetch.Get your form working in 30 seconds
- No credit card required
- Unlimited forms
- 100 submissions/month free