React Router
React Router ist die Standard-Routing-Library für React. Sie ermöglicht Navigation zwischen verschiedenen Views/Pages in deiner Single-Page-Application (SPA).
Installation
# NPM
npm install react-router-dom
# Yarn
yarn add react-router-domBasic Setup
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'
import Contact from './pages/Contact'
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</BrowserRouter>
)
}
export default AppNavigation - Links
import { Link } from 'react-router-dom'
function Navbar() {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
</nav>
)
}
// ⚠️ NICHT <a href="/"> verwenden!
// Das würde die Seite neu ladenNavLink - Active Styling
import { NavLink } from 'react-router-dom'
function Navbar() {
return (
<nav>
<NavLink
to="/"
className={({ isActive }) =>
isActive ? 'nav-link active' : 'nav-link'
}
>
Home
</NavLink>
<NavLink
to="/about"
style={({ isActive }) => ({
color: isActive ? 'red' : 'blue'
})}
>
About
</NavLink>
</nav>
)
}Dynamic Routes - URL Parameters
import { Routes, Route, useParams } from 'react-router-dom'
function App() {
return (
<Routes>
<Route path="/users/:userId" element={<UserProfile />} />
<Route path="/posts/:postId" element={<PostDetail />} />
<Route path="/blog/:category/:slug" element={<BlogPost />} />
</Routes>
)
}
// UserProfile Component
function UserProfile() {
const { userId } = useParams()
return <h1>User Profile: {userId}</h1>
}
// Multi-Parameter
function BlogPost() {
const { category, slug } = useParams()
return (
<div>
<h1>Category: {category}</h1>
<h2>Slug: {slug}</h2>
</div>
)
}
// URL: /blog/react/hooks
// category = 'react'
// slug = 'hooks'Programmatic Navigation
import { useNavigate } from 'react-router-dom'
function LoginPage() {
const navigate = useNavigate()
const handleLogin = async (credentials) => {
const success = await login(credentials)
if (success) {
// Nach Login zum Dashboard
navigate('/dashboard')
}
}
return (
<form onSubmit={handleLogin}>
<button type="submit">Login</button>
</form>
)
}
// Navigation mit State
function ProductList() {
const navigate = useNavigate()
const viewProduct = (product) => {
navigate('/product/' + product.id, {
state: { product }
})
}
}
// Zurück navigieren
function BackButton() {
const navigate = useNavigate()
return <button onClick={() => navigate(-1)}>Zurück</button>
}
// Ersetzen statt Pushen
navigate('/home', { replace: true })Nested Routes
import { Routes, Route, Outlet } from 'react-router-dom'
function App() {
return (
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="dashboard" element={<Dashboard />}>
<Route index element={<DashboardHome />} />
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
</Route>
</Route>
</Routes>
)
}
// Layout Component
function Layout() {
return (
<div>
<Navbar />
<main>
<Outlet /> {/* Child Routes rendern hier */}
</main>
<Footer />
</div>
)
}
// Dashboard Component
function Dashboard() {
return (
<div>
<DashboardSidebar />
<div>
<Outlet /> {/* Nested Routes */}
</div>
</div>
)
}
// URLs:
// / -> Layout + Home
// /about -> Layout + About
// /dashboard -> Layout + Dashboard + DashboardHome
// /dashboard/profile -> Layout + Dashboard + Profile
// /dashboard/settings -> Layout + Dashboard + SettingsProtected Routes
import { Navigate } from 'react-router-dom'
import { useAuth } from './contexts/AuthContext'
// Protected Route Component
function ProtectedRoute({ children }) {
const { isAuthenticated, loading } = useAuth()
if (loading) {
return <div>Loading...</div>
}
if (!isAuthenticated) {
return <Navigate to="/login" replace />
}
return children
}
// In App verwenden
function App() {
return (
<Routes>
<Route path="/login" element={<Login />} />
{/* Protected Routes */}
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>
<Route
path="/profile"
element={
<ProtectedRoute>
<Profile />
</ProtectedRoute>
}
/>
</Routes>
)
}
// Oder mit Outlet
function ProtectedLayout() {
const { isAuthenticated } = useAuth()
if (!isAuthenticated) {
return <Navigate to="/login" />
}
return (
<div>
<Navbar />
<Outlet />
</div>
)
}
function App() {
return (
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<ProtectedLayout />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<Profile />} />
<Route path="/settings" element={<Settings />} />
</Route>
</Routes>
)
}Query Parameters
import { useSearchParams } from 'react-router-dom'
function ProductList() {
const [searchParams, setSearchParams] = useSearchParams()
// Query Parameters lesen
const category = searchParams.get('category')
const sort = searchParams.get('sort')
const page = searchParams.get('page') || '1'
// Query Parameters setzen
const filterByCategory = (cat) => {
setSearchParams({ category: cat, sort, page })
}
const nextPage = () => {
setSearchParams({
category,
sort,
page: String(Number(page) + 1)
})
}
return (
<div>
<h1>Category: {category}</h1>
<button onClick={() => filterByCategory('electronics')}>
Electronics
</button>
<button onClick={nextPage}>Next Page</button>
</div>
)
}
// URL: /products?category=electronics&sort=price&page=2
// category = 'electronics'
// sort = 'price'
// page = '2'404 - Not Found
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
{/* Catch-all Route für 404 */}
<Route path="*" element={<NotFound />} />
</Routes>
)
}
function NotFound() {
const navigate = useNavigate()
return (
<div>
<h1>404 - Seite nicht gefunden</h1>
<p>Die angeforderte Seite existiert nicht.</p>
<button onClick={() => navigate('/')}>
Zurück zur Startseite
</button>
</div>
)
}useLocation Hook
import { useLocation } from 'react-router-dom'
function CurrentPath() {
const location = useLocation()
console.log(location.pathname) // '/dashboard/profile'
console.log(location.search) // '?tab=settings'
console.log(location.hash) // '#section-2'
console.log(location.state) // { from: '/login' }
return (
<div>
<p>Current Path: {location.pathname}</p>
</div>
)
}
// State übergeben
function LoginPage() {
const navigate = useNavigate()
const location = useLocation()
const from = location.state?.from || '/'
const handleLogin = async () => {
// Nach Login zurück zur ursprünglichen Seite
navigate(from, { replace: true })
}
}Lazy Loading - Code Splitting
import { lazy, Suspense } from 'react'
import { Routes, Route } from 'react-router-dom'
// Lazy Load Components
const Home = lazy(() => import('./pages/Home'))
const About = lazy(() => import('./pages/About'))
const Dashboard = lazy(() => import('./pages/Dashboard'))
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>
)
}
// Oder eigene Loading Component
function LoadingSpinner() {
return (
<div className="loading-spinner">
<div className="spinner"></div>
<p>Loading page...</p>
</div>
)
}
<Suspense fallback={<LoadingSpinner />}>
<Routes>...</Routes>
</Suspense>Complete App Example
import {
BrowserRouter,
Routes,
Route,
Link,
Navigate
} from 'react-router-dom'
import { useAuth } from './contexts/AuthContext'
// Layout
function Layout() {
return (
<div>
<Navbar />
<main>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/blog" element={<Blog />} />
<Route path="/blog/:slug" element={<BlogPost />} />
<Route path="/login" element={<Login />} />
{/* Protected Routes */}
<Route element={<ProtectedLayout />}>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/profile" element={<Profile />} />
<Route path="/settings" element={<Settings />} />
</Route>
{/* 404 */}
<Route path="*" element={<NotFound />} />
</Routes>
</main>
<Footer />
</div>
)
}
function Navbar() {
const { isAuthenticated, logout } = useAuth()
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/blog">Blog</Link>
{isAuthenticated ? (
<>
<Link to="/dashboard">Dashboard</Link>
<button onClick={logout}>Logout</button>
</>
) : (
<Link to="/login">Login</Link>
)}
</nav>
)
}
function ProtectedLayout() {
const { isAuthenticated } = useAuth()
if (!isAuthenticated) {
return <Navigate to="/login" replace />
}
return <Outlet />
}
function App() {
return (
<BrowserRouter>
<Layout />
</BrowserRouter>
)
}
export default App📝 Quiz
Was ist der Unterschied zwischen Link und a-Tag?
Tipps & Tricks
Base URL konfigurieren
// Wenn App nicht in Root läuft
<BrowserRouter basename="/my-app">
<Routes>...</Routes>
</BrowserRouter>
// URL: example.com/my-app/about
Redirect Component
import { Navigate } from 'react-router-dom'
// Alte Route zu neuer umleiten
<Route path="/old-page" element={<Navigate to="/new-page" replace />} />
// Conditional Redirect
function Home() {
const { isAuthenticated } = useAuth()
if (isAuthenticated) {
return <Navigate to="/dashboard" />
}
return <h1>Welcome!</h1>
}
Active Link Styling
// Mit className
<NavLink
to="/about"
className={({ isActive }) => isActive ? 'active' : ''}
>
About
</NavLink>
// CSS
.active {
color: blue;
font-weight: bold;
border-bottom: 2px solid blue;
}
Scroll to Top
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
function ScrollToTop() {
const { pathname } = useLocation()
useEffect(() => {
window.scrollTo(0, 0)
}, [pathname])
return null
}
// In App
<BrowserRouter>
<ScrollToTop />
<Routes>...</Routes>
</BrowserRouter>
Häufige Fehler
Fehler 1: a-Tag statt Link
❌ FALSCH:
<a href="/about">About</a>
// Lädt Seite neu! ❌
✅ RICHTIG:
<Link to="/about">About</Link>
// Client-Side Routing ✅
Fehler 2: Router vergessen
❌ FALSCH:
function App() {
return (
<Routes> {/* Error! */}
<Route path="/" element={<Home />} />
</Routes>
)
}
✅ RICHTIG:
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</BrowserRouter>
)
}
Fehler 3: Falsche Pfade
❌ FALSCH:
<Route path="about" element={<About />} />
<Link to="about">About</Link>
// Relative Pfade können problematisch sein
✅ RICHTIG:
<Route path="/about" element={<About />} />
<Link to="/about">About</Link>
// Absolute Pfade sind eindeutig
Fehler 4: useNavigate in Render
❌ FALSCH:
function Component() {
const navigate = useNavigate()
navigate('/home') // Infinite Loop!
return <div>Content</div>
}
✅ RICHTIG:
function Component() {
const navigate = useNavigate()
useEffect(() => {
navigate('/home')
}, [])
// Oder in Event Handler
const handleClick = () => {
navigate('/home')
}
}
Zusammenfassung
Du hast gelernt:
- ✅ React Router für Navigation
- ✅ BrowserRouter + Routes + Route
- ✅ Link und NavLink Components
- ✅ Dynamic Routes mit useParams
- ✅ Programmatic Navigation mit useNavigate
- ✅ Nested Routes mit Outlet
- ✅ Protected Routes implementieren
- ✅ Query Parameters mit useSearchParams
- ✅ 404 Pages mit Wildcard Route
Key Takeaways:
- BrowserRouter um gesamte App wrappen
- Link statt a-Tag verwenden
- NavLink für aktive Links
- useParams für URL-Parameter
- useNavigate für programmatische Navigation
- Protected Routes mit Navigate
- Lazy Loading für bessere Performance
Route Types:
- Static:
/about - Dynamic:
/users/:id - Nested:
/dashboard/profile - Wildcard:
*für 404 - Index:
indexfür Default Route
Best Practices:
- Absolute Pfade verwenden (
/about) - Protected Routes für Auth
- 404 Page implementieren
- Lazy Loading für große Apps
- ScrollToTop Component
Praktische Übungen
Übung 1: Basic Routing
Erstelle eine App mit:
- Home Page
- About Page
- Contact Page
- Navbar mit Links
Übung 2: Blog mit Dynamic Routes
Implementiere:
- /blog - Liste aller Posts
- /blog/:slug - Einzelner Post
- useParams für Slug
Übung 3: Dashboard mit Nested Routes
Baue ein Dashboard:
- /dashboard - Overview
- /dashboard/profile - User Profile
- /dashboard/settings - Settings
- Sidebar Navigation
Übung 4: Protected Routes
Implementiere:
- Login Page
- Protected Dashboard
- Redirect zu Login wenn nicht eingeloggt
- Nach Login redirect zu Dashboard
Übung 5: E-Commerce Routing
Erstelle:
- /products - Product List
- /products/:id - Product Detail
- /cart - Shopping Cart
- /checkout - Checkout (protected)
- Query Params für Filter/Sort
Gut gemacht! 🎉
Du hast "React Router - Navigation in React Apps" abgeschlossen
Artikel bewerten
Bitte einloggen um zu bewerten
Das könnte dich auch interessieren
React Context API - Globaler State ohne Props Drilling
Lerne die React Context API kennen und vermeide Props Drilling. Teile State einfach zwischen Komponenten ohne Redux!
React Custom Hooks - Wiederverwendbare Logik
Lerne Custom Hooks zu erstellen und Code zwischen Komponenten zu teilen. DRY-Prinzip in React mit eigenen Hooks!
React Forms - Input Handling & Validation
Lerne Forms in React zu bauen. Controlled vs Uncontrolled Components, Validation, Multi-Input Forms und Form Libraries.