🧭 Project Introduction
Authentication is one of the most important real-world requirements in React applications. Almost every app needs:
- User registration
- User login
- Session handling
- Protected pages
In this project, we will build a complete Login / Register system using:
- React Hook Form
- Form validation
- LocalStorage
- Protected Routes
🎯 Features of This Project
✔ Register user
✔ Login user
✔ Form validation
✔ Store auth data in LocalStorage
✔ Protected Dashboard route
✔ Logout functionality
✔ Clean folder structure
📁 Project Folder Structure (Best Practice)
src/
├── auth/
│ ├── Login.jsx
│ ├── Register.jsx
│ ├── ProtectedRoute.jsx
│ └── authService.js
├── pages/
│ └── Dashboard.jsx
├── App.jsx
├── main.jsx
└── index.css
🧠 Authentication Strategy (Simple & Clear)
We will:
- Store user info in
localStorage - Check login status before showing protected pages
- Redirect unauthenticated users to Login page
👉 This is frontend-only authentication (perfect for learning).
📦 Step 1: Install Required Packages
npm install react-hook-form react-router-dom
🧩 Step 2: authService.js (Auth Logic)
// src/auth/authService.js
export const registerUser = (data) => {
localStorage.setItem("user", JSON.stringify(data));
};
export const loginUser = (email, password) => {
const user = JSON.parse(localStorage.getItem("user"));
if (user && user.email === email && user.password === password) {
localStorage.setItem("isAuth", "true");
return true;
}
return false;
};
export const logoutUser = () => {
localStorage.removeItem("isAuth");
};
export const isAuthenticated = () => {
return localStorage.getItem("isAuth") === "true";
};
🧩 Step 3: Register.jsx
import { useForm } from "react-hook-form";
import { registerUser } from "./authService";
import { useNavigate } from "react-router-dom";
const Register = () => {
const { register, handleSubmit, formState: { errors } } = useForm();
const navigate = useNavigate();
const onSubmit = (data) => {
registerUser(data);
navigate("/login");
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<h2>Register</h2>
<input
placeholder="Email"
{...register("email", { required: "Email required" })}
/>
{errors.email && <p>{errors.email.message}</p>}
<input
type="password"
placeholder="Password"
{...register("password", {
required: "Password required",
minLength: { value: 6, message: "Min 6 characters" },
})}
/>
{errors.password && <p>{errors.password.message}</p>}
<button type="submit">Register</button>
</form>
);
};
export default Register;
🧩 Step 4: Login.jsx
import { useForm } from "react-hook-form";
import { loginUser } from "./authService";
import { useNavigate } from "react-router-dom";
import { useState } from "react";
const Login = () => {
const { register, handleSubmit } = useForm();
const navigate = useNavigate();
const [error, setError] = useState("");
const onSubmit = (data) => {
const success = loginUser(data.email, data.password);
if (success) {
navigate("/dashboard");
} else {
setError("Invalid credentials");
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
<h2>Login</h2>
<input
placeholder="Email"
{...register("email", { required: true })}
/>
<input
type="password"
placeholder="Password"
{...register("password", { required: true })}
/>
{error && <p>{error}</p>}
<button type="submit">Login</button>
</form>
);
};
export default Login;
🧩 Step 5: ProtectedRoute.jsx
import { Navigate } from "react-router-dom";
import { isAuthenticated } from "./authService";
const ProtectedRoute = ({ children }) => {
return isAuthenticated() ? children : <Navigate to="/login" />;
};
export default ProtectedRoute;
🧩 Step 6: Dashboard.jsx (Protected Page)
import { logoutUser } from "../auth/authService";
import { useNavigate } from "react-router-dom";
const Dashboard = () => {
const navigate = useNavigate();
const handleLogout = () => {
logoutUser();
navigate("/login");
};
return (
<div>
<h1>Dashboard</h1>
<p>Welcome! You are logged in.</p>
<button onClick={handleLogout}>Logout</button>
</div>
);
};
export default Dashboard;
🧩 Step 7: App.jsx (Routing Setup)
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Login from "./auth/Login";
import Register from "./auth/Register";
import Dashboard from "./pages/Dashboard";
import ProtectedRoute from "./auth/ProtectedRoute";
const App = () => {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Register />} />
<Route path="/login" element={<Login />} />
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>
</Routes>
</BrowserRouter>
);
};
export default App;
🎨 Step 8: Basic Styling (index.css)
body {
font-family: Arial, sans-serif;
background: #f4f4f4;
}
form {
max-width: 350px;
margin: 40px auto;
background: white;
padding: 20px;
border-radius: 5px;
}
input {
width: 100%;
margin-top: 10px;
padding: 8px;
}
button {
width: 100%;
margin-top: 15px;
padding: 10px;
}
p {
color: red;
}
🧠 Concepts Applied in This Project
✔ React Router
✔ Protected Routes
✔ React Hook Form
✔ Form Validation
✔ LocalStorage session handling
✔ Clean authentication flow
⚠ Important Notes (Learning Perspective)
🔒 This is not production authentication
👉 Real apps use:
- Backend APIs
- JWT tokens
- Secure cookies
But this project builds strong fundamentals.
🎯 Best Practices Used
✅ Separation of auth logic
✅ Protected routes
✅ Clean redirects
✅ Scalable structure
🧠 Quick Recap
✔ Complete Login / Register app
✔ Protected Dashboard
✔ Session handling with LocalStorage
✔ Real-world routing logic
🎉 Final Conclusion
🎉 Outstanding progress!
You’ve built a real authentication system UI, which is a huge milestone for any React learner.
This project proves you can now:
- Handle authentication flows
- Protect routes
- Manage sessions
- Structure real-world React apps
🚀 What’s Next?
👉 Project 4 — Dashboard with API