How to Create a Contact Form in React (2 Minutes)
Build a fully functional contact form with backend submission. No server code required.
The Problem
You need a contact form on your React website. Users should be able to send you messages. But you don't want to set up a backend server, write API routes, configure a database, or deal with email services.
The Solution
FormFlow provides a useFormFlow hook that handles everything: form state, validation, submission, storage, and email notifications. All in 3 lines of code.
What You'll Build
A contact form with:
- Email field (validated)
- Name field
- Message textarea
- Submit button with loading state
- Backend submission (automatic)
- Email notifications (automatic)
- Spam protection (automatic)
Step 1: Install FormFlow
npm install @formflow.sh/reactStep 2: Get Your API Key
Sign up at formflow.sh and create a free API key. Free tier includes 50 submissions/month.
Add it to your .env.local:
NEXT_PUBLIC_FORMFLOW_API_KEY=ff_live_your_key_hereStep 3: Create the Form Component
Here's the complete code:
import { useFormFlow } from '@formflow.sh/react';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
export function ContactForm() {
const { register, handleSubmit, formState } = useFormFlow({
apiKey: process.env.NEXT_PUBLIC_FORMFLOW_API_KEY,
onSuccess: () => alert('Thanks! We\'ll get back to you soon.'),
});
return (
<form onSubmit={handleSubmit} className="space-y-4 max-w-md">
<div>
<Label htmlFor="email">Email *</Label>
<Input
{...register('email')}
id="email"
type="email"
placeholder="you@example.com"
required
/>
</div>
<div>
<Label htmlFor="name">Name *</Label>
<Input
{...register('name')}
id="name"
placeholder="John Doe"
required
/>
</div>
<div>
<Label htmlFor="message">Message *</Label>
<Textarea
{...register('message')}
id="message"
placeholder="How can we help you?"
rows={5}
required
/>
</div>
<Button type="submit" disabled={formState.isSubmitting}>
{formState.isSubmitting ? 'Sending...' : 'Send Message'}
</Button>
</form>
);
}That's It!
Your contact form is complete and fully functional. Here's what happens when someone submits:
- Client-side validation runs (email format, required fields)
- Form data is sent to FormFlow backend
- Spam protection filters out bots
- Submission is stored in your dashboard
- You receive an email notification
- User sees success message
Customization Options
Add More Fields
Add any fields you want:
<div>
<Label htmlFor="phone">Phone (optional)</Label>
<Input {...register('phone')} id="phone" type="tel" />
</div>
<div>
<Label htmlFor="company">Company (optional)</Label>
<Input {...register('company')} id="company" />
</div>Add Validation
Use react-hook-form validation:
<Input
{...register('email', {
required: 'Email is required',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address',
},
})}
id="email"
type="email"
/>
{formState.errors.email && (
<p className="text-red-500 text-sm">
{formState.errors.email.message}
</p>
)}Customize Success Action
Instead of alert, redirect or show custom message:
const { register, handleSubmit, formState } = useFormFlow({
apiKey: process.env.NEXT_PUBLIC_FORMFLOW_API_KEY,
onSuccess: () => {
router.push('/thank-you');
// or show custom success component
},
onError: (error) => {
console.error('Failed to send:', error);
// show error message to user
},
});View Submissions
All submissions appear in your FormFlow dashboard at formflow.sh/dashboard. You can:
- View all submissions
- Export to CSV
- Set up email notifications
- Configure webhooks
Works With Any UI Library
The example above uses shadcn/ui, but FormFlow works with any UI library:
Material-UI
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
<TextField {...register('email')} label="Email" type="email" />
<Button type="submit">Send</Button>Chakra UI
import { Input, Button } from '@chakra-ui/react';
<Input {...register('email')} placeholder="Email" />
<Button type="submit">Send</Button>Native HTML
<input {...register('email')} type="email" required />
<button type="submit">Send</button>Why FormFlow?
No Backend Code
With traditional solutions, you'd need to:
- Create an API endpoint (
/api/contact) - Set up a database
- Configure email service (SendGrid, etc.)
- Handle validation and spam protection
- Deploy and maintain the backend
FormFlow handles all of this automatically.
Production Ready
FormFlow includes everything you need:
- ✓ Rate limiting
- ✓ Spam protection (honeypot)
- ✓ Email notifications
- ✓ Data storage
- ✓ CSV export
- ✓ Webhook support
Next Steps
Related Resources
- Contact Form Solutions - Complete overview of contact form options
- FormFlow vs react-hook-form - See the differences