L6: Add SignInPage to Router
Configure routing for authentication
Now let's make the sign-in page accessible through React Router! 🛤️
Why Add a Route?
Benefits of /sign-in route:
- ✅ Clean URL (sharable, bookmarkable)
- ✅ Browser history works (back/forward buttons)
- ✅ Easy to redirect users
- ✅ SEO-friendly (if needed)
- ✅ Professional standard
User experience:
Before: No way to access sign-in page
After: User can visit yourdomain.com/sign-inUpdate Router Configuration
Add the sign-in route to your existing router:
import { Routes, Route } from 'react-router-dom';
import HomePage from '@/pages/HomePage';
import FavoritesPage from '@/pages/FavoritesPage';
import NotFoundPage from '@/pages/NotFoundPage';
import SignInPage from '@/pages/SignInPage'; // ← New import
import { useAuth } from '@/contexts/AuthContext';
function AppContent() {
const { user, isLoading } = useAuth();
if (isLoading) {
return (
<div className="loading-container">
<div className="spinner"></div>
<p>Loading...</p>
</div>
);
}
return (
<div className="app">
{user && <Navbar />}
<main className="main-content">
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/favorites" element={<FavoritesPage />} />
<Route path="/sign-in" element={<SignInPage />} /> {/* ← New route */}
<Route path="*" element={<NotFoundPage />} />
</Routes>
</main>
</div>
);
}
function App() {
return (
<AuthProvider>
<BrowserRouter>
<AppContent />
</BrowserRouter>
</AuthProvider>
);
}
export default App;Understanding Route Order
Test the Route
Start your development server:
npm run devVisit the sign-in page:
Open browser and navigate to:
http://localhost:5173/sign-inYou should see your beautiful sign-in page! 🎉
Test navigation:
Try these URLs manually:
http://localhost:5173/→ HomePagehttp://localhost:5173/sign-in→ SignInPagehttp://localhost:5173/favorites→ FavoritesPagehttp://localhost:5173/unknown→ NotFoundPage (404)
Check browser history:
- Visit
/ - Visit
/sign-in - Click browser back button
- Should return to
/
✅ History works!
Add Navigation Links
Make it easy to get to sign-in page:
Automatically redirect when needed:
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '@/contexts/AuthContext';
function ProtectedComponent() {
const { user } = useAuth();
const navigate = useNavigate();
useEffect(() => {
if (!user) {
// User not signed in, redirect to sign-in page
navigate('/sign-in');
}
}, [user, navigate]);
if (!user) {
return null; // Or loading spinner
}
return (
<div>
{/* Protected content */}
</div>
);
}When to use:
- Protecting specific features
- After sign-out
- When session expires
Better approach (coming in L13-14):
We'll create a proper <Protected> wrapper component!
Common Routing Patterns
For complex page structures:
<Routes>
{/* Top-level routes */}
<Route path="/" element={<HomePage />} />
{/* Nested routes (layout) */}
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="settings" element={<Settings />} />
<Route path="profile" element={<Profile />} />
</Route>
</Routes>URLs created:
/dashboard→ DashboardHome/dashboard/settings→ Settings/dashboard/profile→ Profile
All share DashboardLayout wrapper!
Example layout:
function DashboardLayout() {
return (
<div className="dashboard">
<Sidebar />
<main>
<Outlet /> {/* Nested route renders here */}
</main>
</div>
);
}For dynamic content:
<Routes>
<Route path="/venues/:id" element={<VenuePage />} />
<Route path="/user/:username" element={<ProfilePage />} />
</Routes>Access parameters:
import { useParams } from 'react-router-dom';
function VenuePage() {
const { id } = useParams();
// URL: /venues/123
// id = "123"
return <div>Viewing venue {id}</div>;
}Multiple parameters:
<Route path="/cities/:country/:city" element={<CityPage />} />
// URL: /cities/norway/oslo
// country = "norway"
// city = "oslo"For filters, search, pagination:
// URL: /search?query=beach&guests=4&page=2Access query parameters:
import { useSearchParams } from 'react-router-dom';
function SearchPage() {
const [searchParams, setSearchParams] = useSearchParams();
const query = searchParams.get('query'); // "beach"
const guests = searchParams.get('guests'); // "4"
const page = searchParams.get('page'); // "2"
return <div>Searching for: {query}</div>;
}Update query parameters:
// Add/update parameter
setSearchParams({ query: 'mountains', guests: '2' });
// URL becomes: /search?query=mountains&guests=2
// Keep existing, add new
setSearchParams(prev => {
prev.set('page', '3');
return prev;
});
// URL becomes: /search?query=mountains&guests=2&page=3Troubleshooting Routes
What's Next?
In Lesson 7, we'll:
- Create SignInForm component with React Hook Form
- Add Zod schema validation
- Build beautiful form fields
- Handle form state and errors
✅ Lesson Complete! Sign-in page is now accessible via /sign-in route!
Key Takeaways
- ✅ Routes map URLs to components (
/sign-in→SignInPage) - ✅ Route order matters (specific before catch-all)
- ✅ Catch-all
*route handles 404 errors - ✅ Import component before adding to Routes
- ✅ Test navigation with browser URL bar and history
- ✅ Add links to make routes accessible
- ✅ Use
navigate()for programmatic navigation - ✅ Protected routes coming in later lessons