Master form handling and validation in React
Managing form inputs with React state
import { useState } from 'react';
const LoginForm = () => {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
};
return (
);
};
Implementing client-side validation
import { useState } from 'react';
const RegisterForm = () => {
const [formData, setFormData] = useState({
email: '',
password: '',
confirmPassword: ''
});
const [errors, setErrors] = useState({});
const validateForm = () => {
const newErrors = {};
// Email validation
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
newErrors.email = 'Email is invalid';
}
// Password validation
if (!formData.password) {
newErrors.password = 'Password is required';
} else if (formData.password.length < 6) {
newErrors.password = 'Password must be at least 6 characters';
}
// Confirm password
if (formData.password !== formData.confirmPassword) {
newErrors.confirmPassword = 'Passwords do not match';
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = (e) => {
e.preventDefault();
if (validateForm()) {
// Submit form
console.log('Form is valid', formData);
}
};
return (
);
};
Handling form submission and API integration
import { useState } from 'react';
const ContactForm = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
message: ''
});
const [status, setStatus] = useState({
loading: false,
error: null,
success: false
});
const handleSubmit = async (e) => {
e.preventDefault();
setStatus({ loading: true, error: null, success: false });
try {
const response = await fetch('/api/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
if (!response.ok) {
throw new Error('Failed to submit form');
}
setStatus({
loading: false,
error: null,
success: true
});
setFormData({ name: '', email: '', message: '' });
} catch (error) {
setStatus({
loading: false,
error: error.message,
success: false
});
}
};
if (status.success) {
return Thank you for your message!;
}
return (
);
};
Creating reusable form logic
import { useState } from 'react';
const useForm = (initialValues, validate) => {
const [values, setValues] = useState(initialValues);
const [errors, setErrors] = useState({});
const [touched, setTouched] = useState({});
const handleChange = (e) => {
const { name, value } = e.target;
setValues(prev => ({
...prev,
[name]: value
}));
};
const handleBlur = (e) => {
const { name } = e.target;
setTouched(prev => ({
...prev,
[name]: true
}));
if (validate) {
const validationErrors = validate(values);
setErrors(validationErrors);
}
};
const handleSubmit = (onSubmit) => async (e) => {
e.preventDefault();
if (validate) {
const validationErrors = validate(values);
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
await onSubmit(values);
}
} else {
await onSubmit(values);
}
};
return {
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit
};
};
// Using the custom hook
const SignupForm = () => {
const {
values,
errors,
touched,
handleChange,
handleBlur,
handleSubmit
} = useForm(
{ email: '', password: '' },
values => {
const errors = {};
if (!values.email) errors.email = 'Required';
if (!values.password) errors.password = 'Required';
return errors;
}
);
const onSubmit = async (values) => {
// Submit to API
console.log('Form submitted:', values);
};
return (
);
};