This document explains the step-by-step process of creating a form with validation using React State and custom validation functions without any packages or library.
Prerequisites
Refer React + Vite + Tailwind docs for setup or simply follow the below steps.
- Create React Project using Vite
npm create vite@latest formValidation -- --template react
cd formValidation
Install Tailwind CSS
npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
Configure your template paths (tailwind.config.js)
/** @type {import('tailwindcss').Config} */
export default {
content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
};
- Add Tailwind directives to your CSS (index.css)
@tailwind base;
@tailwind components;
@tailwind utilities;
Let's get started with building a custom Form Validation with React ๐
Initialize React Component
import { useState } from 'react';
const Form = () => {
// State management here
// Return JSX here
};
export default Form;
Define State Variable
const [fname, setFName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [error, setError] = useState({
fname: '',
lastName: '',
email: '',
password: '',
confirmPassword: '',
});
Create Custom Validation Functions
const validateFirstName = (name) =>
name.length > 0 ? '' : 'First name is required';
const validateLastName = (name) =>
name.length > 0 ? '' : 'Last name is required';
const validateEmail = (email) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) ? '' : 'Email is invalid';
const validatePassword = (password) =>
password.length >= 8 ? '' : 'Password must be at least 8 characters';
const validateConfirmPassword = (password, confirmPassword) =>
password === confirmPassword ? '' : 'Passwords do not match';
Handle Form Submissions
const handleSubmit = (e) => {
// prevent default form submission behavior
e.preventDefault();
// validate the fields
const newErrors = {
fname: validateFirstName(fname),
lastName: validateLastName(lastName),
email: validateEmail(email),
password: validatePassword(password),
confirmPassword: validateConfirmPassword(password, confirmPassword),
};
setError(newErrors);
// if there is error it would return it
if (Object.values(newErrors).some((error) => error)) {
return;
}
console.log('Submitted:', { fname, lastName, email, password });
// clear the input fields after submission
setFName('');
setLastName('');
setEmail('');
setPassword('');
setConfirmPassword('');
};
Render the Form
return (
<div className="min-h-screen flex items-center justify-center bg-gray-100">
<form
className="bg-white p-8 rounded shadow-md w-full max-w-md"
onSubmit={handleSubmit}>
<div className="text-center text-cyan-400 text-3xl mb-6 font-semibold">
Form Validation
</div>
<div className="mb-4">
<label htmlFor="fname" className="block text-gray-700">
First Name:
</label>
<input
type="text"
id="fname"
value={fname}
onChange={(e) => setFName(e.target.value)}
placeholder="Enter your first name"
className="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-cyan-400"
required
/>
{error.fname && (
<div className="text-red-500 text-sm mt-1">{error.fname}</div>
)}
</div>
<div className="mb-4">
<label htmlFor="lastName" className="block text-gray-700">
Last Name:
</label>
<input
type="text"
id="lastName"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
placeholder="Enter your last name"
className="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-cyan-400"
required
/>
{error.lastName && (
<div className="text-red-500 text-sm mt-1">{error.lastName}</div>
)}
</div>
<div className="mb-4">
<label htmlFor="email" className="block text-gray-700">
Email:
</label>
<input
type="email"
id="email"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-cyan-400"
required
/>
{error.email && (
<div className="text-red-500 text-sm mt-1">{error.email}</div>
)}
</div>
<div className="mb-4">
<label htmlFor="password" className="block text-gray-700">
Password:
</label>
<input
type="password"
id="password"
placeholder="Enter your password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-cyan-400"
required
/>
{error.password && (
<div className="text-red-500 text-sm mt-1">{error.password}</div>
)}
</div>
<div className="mb-4">
<label htmlFor="confirmPassword" className="block text-gray-700">
Confirm Password:
</label>
<input
type="password"
id="confirmPassword"
placeholder="Confirm your password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-cyan-400"
required
/>
{error.confirmPassword && (
<div className="text-red-500 text-sm mt-1">
{error.confirmPassword}
</div>
)}
</div>
<button
type="submit"
className="w-full bg-cyan-400 text-white py-2 rounded hover:bg-cyan-500 focus:outline-none focus:ring-2 focus:ring-cyan-400">
Submit
</button>
</form>
</div>
);
Add Form Component to App.jsx. Don't forget this(:-D)
import Form from './Form';
const App = () => {
return <Form />;
};
export default App;
Final Output
Summary
By following this steps, you create a form with proper state management, validation and error handling in React.
Each input field is validated using custom functions, and error message are displayed appropriately.
The form submission is handled efficiently, ensuring that all validations pass before processing.
Connect with me on Twitter ๐๐ป
๐ Falak097
Check out my GitHub for complete code reference and more such React, JS and front-end development projects.