Authentication is one of the most intimidating topics for beginners in React, especially when they hear terms like JWT, OAuth, and session cookies. But in this article, I'm going to break it down in a way that's practical, beginner-friendly, and focused on helping you understand how to store user data securely using just React and localStorage.
We’re going to build a simple app with login, logout, and a protected dashboard.
What You’ll Learn
- How to set up a basic React app with routes
- How to handle login and store user data in localStorage
- How to protect a route (e.g., dashboard)
- How to show login/logout conditionally
Step 1: Set Up Your React App
Use create-react-app or vite. For this example, I’ll use create-react-app:
npx create-react-app react-auth-localstorage
cd react-auth-localstorage
npm start
Step 2: Folder Structure
Let’s keep things clean:
src/
|-- components/
| |-- Home.js
| |-- Login.js
| |-- Dashboard.js
|-- App.js
|-- index.js
Step 3: Install React Router
-npm install react-router-dom
Now update App.js to add routing:
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './components/Home';
import Login from './components/Login';
import Dashboard from './components/Dashboard';
function App() {
return (
<Router>
<Routes>
<Route path='/' element={<Home />} />
<Route path='/login' element={<Login />} />
<Route path='/dashboard' element={<Dashboard />} />
</Routes>
</Router>
);
}
export default App;
Step 4: Creating the Login Component
Let’s start simple. Our login form will accept email and password, and we’ll simulate login by storing a fake token in localStorage.
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const navigate = useNavigate();
const handleLogin = (e) => {
e.preventDefault();
// Simulate login and save to localStorage
if (email && password) {
localStorage.setItem('user', JSON.stringify({ email }));
navigate('/dashboard');
} else {
alert('Please fill in all fields');
}
};
return (
<form onSubmit={handleLogin}>
<h2>Login</h2>
<input type='email' placeholder='Email' value={email} onChange={e => setEmail(e.target.value)} /><br />
<input type='password' placeholder='Password' value={password} onChange={e => setPassword(e.target.value)} /><br />
<button type='submit'>Login</button>
</form>
);
};
export default Login;
Step 5: Dashboard with Logout and Protection
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
const Dashboard = () => {
const navigate = useNavigate();
useEffect(() => {
const user = JSON.parse(localStorage.getItem('user'));
if (!user) {
navigate('/login');
}
}, [navigate]);
const handleLogout = () => {
localStorage.removeItem('user');
navigate('/login');
};
return (
<div>
<h2>Welcome to Dashboard</h2>
<button onClick={handleLogout}>Logout</button>
</div>
);
};
export default Dashboard;
Step 6: Home Component (Public Route)
const Home = () => {
return (
<div>
<h1>Welcome to Our App</h1>
<p>Click login to continue</p>
</div>
);
};
export default Home;
Final Notes:
This is not production-grade authentication but is great for understanding state, routing, and localStorage.
Never store real tokens or passwords in localStorage in production apps.
Top comments (0)