Click files to view code →
Create a contact form component that allows users to send messages. The form should include name, email, subject, and message fields with validation, submission handling, and success/error feedback.
[!TIP] Goal
Use React's
useState[!IMPORTANT] Requirements
Key Topics:
Plan of Action:
import React, { useState } from 'react';
import './ContactForm.css';
function ContactForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
subject: '',
message: ''
});
const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState(null); // 'success' or 'error'
// Validation functions
const validateName = (name) => {
if (!name.trim()) return 'Name is required';
if (name.trim().length < 2) return 'Name must be at least 2 characters';
return '';
};
const validateEmail = (email) => {
if (!email.trim()) return 'Email is required';
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) return 'Please enter a valid email';
return '';
};
const validateSubject = (subject) => {
if (!subject.trim()) return 'Subject is required';
if (subject.trim().length < 3) return 'Subject must be at least 3 characters';
return '';
};
const validateMessage = (message) => {
if (!message.trim()) return 'Message is required';
if (message.trim().length < 10) return 'Message must be at least 10 characters';
if (message.length > 1000) return 'Message must be less than 1000 characters';
return '';
};
// Handle input changes
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
// ...CSS (ContactForm.css):
.contact-form-container {
max-width: 600px;
margin: 2rem auto;
padding: 2rem;
background: #fff;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
font-family: Arial, sans-serif;
}
.contact-form-header {
text-align: center;
margin-bottom: 2rem;
}
.contact-form-header h2 {
margin: 0 0 0.5rem 0;
color: #333;
}
.contact-form-header p {
margin: 0;
color: #666;
font-size: 0.95rem;
}
.alert {
padding: 1rem;
border-radius: 6px;
margin-bottom: 1.5rem;
font-weight: 500;
}
.alert-success {
background-color: #e8f5e9;
color: #2e7d32;
border-left: 4px solid #4caf50;
}
.alert-error {
background-color: #ffebee;
color: #c62828;
border-left: 4px solid #f44336;
}
.contact-form {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
// ...Best Practices:
Email Service Integration Examples:
// Using EmailJS
import emailjs from '@emailjs/browser';
const handleSubmit = async (e) => {
e.preventDefault();
if (!validateForm()) return;
setIsSubmitting(true);
try {
await emailjs.send(
'YOUR_SERVICE_ID',
'YOUR_TEMPLATE_ID',
formData,
'YOUR_PUBLIC_KEY'
);
setSubmitStatus('success');
} catch (error) {
setSubmitStatus('error');
} finally {
setIsSubmitting(false);
}
};
// Using Formspree
const handleSubmit = async (e) => {
e.preventDefault();
if (!validateForm()) return;
setIsSubmitting(true);
try {
const response = await fetch('https://formspree.io/f/YOUR_FORM_ID', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formData)
});
if (response.ok) {
setSubmitStatus('success');
} else {
throw new Error('Failed');
}
} catch (error) {
setSubmitStatus('error');
} finally {
setIsSubmitting(false);
}
};Testing:
Real-World Use Cases:
This contact form is production-ready and can be integrated with any email service or backend API.
No files open
Click a file in the explorer to view