Routing dengan React Router
Navigasi multi-halaman dengan React Router tanpa reload halaman
Apa itu React Router?
React Router adalah library untuk routing di aplikasi React. Dengan React Router, kita bisa membuat aplikasi multi-halaman (Single Page Application) tanpa reload halaman.
Single Page Application (SPA)
SPA adalah aplikasi web yang hanya load satu halaman HTML, kemudian secara dinamis mengupdate konten saat user berinteraksi dengan aplikasi. Navigasi terasa sangat cepat karena tidak ada page reload.
Instalasi React Router
npm install react-router-domSetup Basic Routing
Buat Component About
Buat halaman About untuk demonstrasi routing:
import React from 'react';
import Header from '../../components/Header/Header';
import './About.css';
function About() {
return (
<div className="about">
<Header
title="About Task Manager"
description="Learn more about our app"
/>
<main className="container">
<div className="about-content">
<h2>Welcome to Task Manager</h2>
<p>
Task Manager adalah aplikasi sederhana yang dibuat dengan React
untuk membantu Anda mengelola tugas sehari-hari dengan mudah dan efisien.
</p>
<h3>Fitur:</h3>
<ul>
<li>Tambah, hapus, dan tandai tugas sebagai selesai</li>
<li>Penyimpanan lokal di browser Anda</li>
<li>Antarmuka pengguna yang responsif dan intuitif</li>
<li>Statistik tugas real-time</li>
</ul>
<h3>Teknologi:</h3>
<p>
Aplikasi ini dibangun menggunakan React dengan functional components
dan Hooks. Kami juga menggunakan localStorage untuk menyimpan data
Anda secara lokal.
</p>
</div>
</main>
</div>
);
}
export default About;.about-content {
background-color: white;
border-radius: 8px;
margin-top: 2rem;
padding: 2rem;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.about-content h2 {
color: #3498db;
margin-top: 0;
}
.about-content h3 {
margin-top: 1.5rem;
margin-bottom: 0.5rem;
color: #2c3e50;
}
.about-content ul {
padding-left: 1.5rem;
}
.about-content li {
margin-bottom: 0.5rem;
}Buat Navigation Component
import React from 'react';
import { Link } from 'react-router-dom';
import './Navbar.css';
function Navbar() {
return (
<nav className="navbar">
<div className="container">
<div className="logo">
<Link to="/">Task Manager</Link>
</div>
<ul className="nav-links">
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</div>
</nav>
);
}
export default Navbar;.navbar {
background-color: #2c3e50;
padding: 1rem 0;
}
.navbar .container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
.logo a {
color: white;
font-size: 1.5rem;
font-weight: bold;
text-decoration: none;
}
.nav-links {
display: flex;
list-style: none;
margin: 0;
padding: 0;
gap: 1.5rem;
}
.nav-links a {
color: #ecf0f1;
text-decoration: none;
font-size: 1rem;
transition: color 0.2s;
}
.nav-links a:hover {
color: #3498db;
}Setup Router di App.jsx
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Navbar from './components/Navbar/Navbar';
import Home from './pages/Home/Home';
import About from './pages/About/About';
import './App.css';
function App() {
return (
<Router>
<div className="App">
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</div>
</Router>
);
}
export default App;Komponen Router Penting
BrowserRouter
Wrapper utama yang menyediakan routing context:
import { BrowserRouter as Router } from 'react-router-dom';
<Router>
{/* App content */}
</Router>Routes dan Route
Routes berisi semua Route definitions:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<UserDetail />} />
<Route path="*" element={<NotFound />} />
</Routes>Link dan NavLink
Link untuk navigasi tanpa reload:
import { Link, NavLink } from 'react-router-dom';
// Basic link
<Link to="/about">About</Link>
// NavLink dengan active state
<NavLink
to="/about"
className={({ isActive }) => isActive ? 'active' : ''}
>
About
</NavLink>Link vs <a>
Selalu gunakan <Link> dari React Router, bukan <a> tag HTML biasa. <Link> mencegah page reload dan membuat navigasi lebih cepat.
URL Parameters
Untuk dynamic routes dengan parameters:
// Route definition
<Route path="/users/:id" element={<UserDetail />} />
// Component
import { useParams } from 'react-router-dom';
function UserDetail() {
const { id } = useParams();
return <div>User ID: {id}</div>;
}Navigate Programmatically
Untuk navigasi dari JavaScript (bukan dari Link):
import { useNavigate } from 'react-router-dom';
function MyComponent() {
const navigate = useNavigate();
const handleSubmit = () => {
// Do something...
navigate('/success');
};
return <button onClick={handleSubmit}>Submit</button>;
}Nested Routes
Untuk membuat nested navigation:
// Parent route
<Route path="/dashboard" element={<Dashboard />}>
<Route path="stats" element={<Stats />} />
<Route path="settings" element={<Settings />} />
</Route>
// Dashboard component
import { Outlet } from 'react-router-dom';
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<Outlet /> {/* Child routes render here */}
</div>
);
}404 Not Found Page
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>import React from 'react';
import { Link } from 'react-router-dom';
function NotFound() {
return (
<div style={{ textAlign: 'center', padding: '2rem' }}>
<h1>404 - Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<Link to="/">Go Home</Link>
</div>
);
}
export default NotFound;Protected Routes
Untuk routes yang membutuhkan authentication:
import { Navigate } from 'react-router-dom';
function ProtectedRoute({ children, isAuthenticated }) {
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return children;
}
// Usage
<Route
path="/dashboard"
element={
<ProtectedRoute isAuthenticated={isLoggedIn}>
<Dashboard />
</ProtectedRoute>
}
/>Query Parameters
Untuk membaca query string dari URL:
import { useSearchParams } from 'react-router-dom';
function SearchPage() {
const [searchParams, setSearchParams] = useSearchParams();
const query = searchParams.get('q');
return <div>Search: {query}</div>;
}
// URL: /search?q=react
// query akan bernilai "react"Update App.css
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
background-color: #f4f7f9;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
.App {
min-height: 100vh;
}Test Routing
Coba navigate antara Home dan About page. Perhatikan bahwa halaman berganti tanpa reload, dan URL di address bar berubah!
Best Practices
- Gunakan BrowserRouter - Lebih baik dari HashRouter untuk production
- Lazy Loading - Load components hanya saat dibutuhkan dengan
React.lazy() - Meaningful URLs -
/users/123lebih baik dari/page?id=123 - Handle 404 - Selalu sediakan catch-all route untuk 404
- Scroll to Top - Reset scroll position saat navigate ke halaman baru
Latihan
- Tambahkan halaman "Contact" dengan form
- Implementasikan route dengan parameter untuk detail task
- Buat nested routes untuk settings page
- Tambahkan breadcrumb navigation
- Implementasikan back button dengan
useNavigate
Apa Selanjutnya?
Selanjutnya kita akan belajar membuat Custom Hooks untuk logic yang reusable!
