/event/one ํ์ด์ง์ /event/two ํ์ด์ง๋ฅผ nested routes๋ฅผ ์ฌ์ฉํด์ ๋ง๋ค์ด๋ด
์๋ค!
React๋ HTML์ ์ด์๊ฒ ๋ง๋ค์ด์ฃผ๋ ์์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ ๋ฟ์ ๋๋ค. ๋ง๋ค ํ์ผ๋ค์ 95%๊ฐ .js ํ์ผ์ด๋ฏ๋ก ๋น์ทํ .js ํ์ผ๋ผ๋ฆฌ ๋ฌถ์ด์ ํด๋๋ฅผ ๊ตฌ์ฑํ๋ฉด ๋ฉ๋๋ค!
src/
โโโ components/ # ์ปดํฌ๋ํธ ์ญํ ํ๋ js ํ์ผ
โโโ routes/ # ํ์ด์ง ์ญํ ํ๋ js ํ์ผ (๋๋ pages/)
โโโ utils/ # ์์ฃผ ์ฐ๋ ํจ์๋ค
โโโ App.jsx
ํ์ํ ๋๋ง๋ค ํด๋๋ฅผ ์ถ๊ฐ๋ก ๋ง๋ค์ด ์ฌ์ฉํ์ธ์! ๐ง
import { Routes, Route, Link, useNavigate, Outlet } from 'react-router-dom'
Link ์ปดํฌ๋ํธ๊ฐ ๋ชป์๊ฒผ๋ค๋ฉด useNavigate()๋ฅผ ์ฌ์ฉํด๋ณด์ธ์!
function App(){
let navigate = useNavigate()
return (
// ์๋ต
<button onClick={() => { navigate('/detail') }}>์ด๋๋ฒํผ</button>
)
}
useNavigate(): ํ์ด์ง ์ด๋์์ผ์ฃผ๋ ํจ์ ๋ฐํnavigate('/detail'): /detail ํ์ด์ง๋ก ์ด๋navigate(-1): ๋ค๋ก 1๋ฒ ๊ฐ๊ธฐnavigate(2): ์์ผ๋ก 2๋ฒ ๊ฐ๊ธฐ์ซ์๋ฅผ ๋ฃ์ผ๋ฉด ๋ธ๋ผ์ฐ์ ํ์คํ ๋ฆฌ ๊ธฐ๋ฐ ์ด๋์ด ๊ฐ๋ฅํฉ๋๋ค! โฎ๏ธโญ๏ธ
์ ์ ๊ฐ ์กด์ฌํ์ง ์๋ ๊ฒฝ๋ก๋ก ์ ์ํ์ ๋ "์๋ ํ์ด์ง์ ๋๋ค" ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ค๋ฉด:
<Route path="*" element={ <div>์๋ํ์ด์ง์</div> } />
path="*": ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ์๋ฏธ/detail ๋ฑ)์ด ์๋ ์ด์ํ ํ์ด์ง ์ ์ ์ * ๊ฒฝ๋ก๋ก ์๋ด/about/member: ํ์ฌ ๋ฉค๋ฒ ์๊ฐ ํ์ด์ง/about/location: ํ์ฌ ์์น ์๊ฐ ํ์ด์ง<Route path="/about/member" element={ <div>๋ฉค๋ฒ๋ค</div> } />
<Route path="/about/location" element={ <div>ํ์ฌ์์น</div> } />
<Route path="/about" element={ <About/> }>
<Route path="member" element={ <div>๋ฉค๋ฒ๋ค</div> } />
<Route path="location" element={ <div>ํ์ฌ์์น</div> } />
</Route>
<Route> ์์ <Route>๋ฅผ ๋ฃ๋ ๊ฒ์ด Nested routes/about/member ์ ์ ์: <About> + <div>๋ฉค๋ฒ๋ค</div> ํ์/about/location ์ ์ ์: <About> + <div>ํ์ฌ์์น</div> ํ์Nested routes์์ ์์ element๋ค์ ์ด๋์ ๋ณด์ฌ์ค์ง ์ง์ ํ๋ ์ปดํฌ๋ํธ:
function About(){
return (
<div>
<h4>aboutํ์ด์ง์</h4>
<Outlet></Outlet>
</div>
)
}
<Outlet>: nested routes ์์ element๋ค์ด ํ์๋ ์์น/about/member ์ ์ ์ <Outlet> ์๋ฆฌ์ <div>๋ฉค๋ฒ๋ค</div> ํ์URL์ ๋ฐ๊ฟ ๋๋ง๋ค ๋ค๋ฅธ UI๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ๋ ๋์ UI๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ ์ค ํ๋์ ๋๋ค!
Link ์ปดํฌ๋ํธ:
<Link to="/detail">์์ธํ์ด์ง๋ก</Link>
useNavigate ํ :
const navigate = useNavigate();
const handleSubmit = (data) => {
// ํผ ์ ์ถ ํ ํ์ด์ง ์ด๋
submitForm(data);
navigate('/success');
};
1. replace ์ต์
// ํ์คํ ๋ฆฌ์ ์ ํญ๋ชฉ ์ถ๊ฐ (๊ธฐ๋ณธ๊ฐ)
navigate('/login');
// ํ์ฌ ํ์คํ ๋ฆฌ ํญ๋ชฉ ๊ต์ฒด (๋ค๋ก๊ฐ๊ธฐ ์ ์ด์ ํ์ด์ง๋ก ์ ๊ฐ)
navigate('/login', { replace: true });
2. state ์ ๋ฌ
navigate('/profile', {
state: {
from: location.pathname,
userInfo: userData
}
});
// ๋ชฉ์ ์ง์์ state ๋ฐ๊ธฐ
const location = useLocation();
const { from, userInfo } = location.state || {};
1. ๋์๋ณด๋ ๋ ์ด์์
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="analytics" element={<Analytics />} />
<Route path="settings" element={<Settings />} />
<Route path="profile" element={<Profile />} />
</Route>
function DashboardLayout() {
return (
<div className="dashboard">
<Sidebar />
<main>
<Outlet />
</main>
</div>
);
}
2. index ๋ผ์ฐํธ ํ์ฉ
<Route path="/products" element={<ProductsLayout />}>
<Route index element={<ProductsList />} /> {/* /products */}
<Route path="new" element={<NewProduct />} /> {/* /products/new */}
<Route path=":id" element={<ProductDetail />} /> {/* /products/123 */}
</Route>
1. ์ธ์ฆ์ด ํ์ํ ๋ผ์ฐํธ
function ProtectedRoute({ children }) {
const navigate = useNavigate();
const { user } = useAuth();
useEffect(() => {
if (!user) {
navigate('/login', { replace: true });
}
}, [user, navigate]);
return user ? children : null;
}
<Route path="/admin" element={
<ProtectedRoute>
<AdminPanel />
</ProtectedRoute>
} />
2. ๊ถํ ๊ธฐ๋ฐ ๋ผ์ฐํ
function RoleBasedRoute({ children, requiredRole }) {
const { user } = useAuth();
if (!user || user.role !== requiredRole) {
return <Navigate to="/unauthorized" replace />;
}
return children;
}
1. ๋ผ์ฐํธ๋ณ ์๋ฌ ๋ฐ์ด๋๋ฆฌ
<Route path="/dashboard" element={
<ErrorBoundary fallback={<DashboardError />}>
<Dashboard />
</ErrorBoundary>
} />
2. ๊ณ์ธต์ 404 ์ฒ๋ฆฌ
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="products" element={<Products />} />
<Route path="*" element={<NotFound />} />
</Route>
</Routes>
1. ๋ผ์ฐํธ ๊ธฐ๋ฐ ์ฝ๋ ์คํ๋ฆฌํ
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));
<Route path="/dashboard" element={
<Suspense fallback={<LoadingSpinner />}>
<Dashboard />
</Suspense>
} />
2. ํ๋ฆฌ๋ก๋ฉ
// ๋ง์ฐ์ค ํธ๋ฒ ์ ์ปดํฌ๋ํธ ๋ฏธ๋ฆฌ ๋ก๋
const DashboardLink = () => {
const handleMouseEnter = () => {
import('./pages/Dashboard'); // ํ๋ฆฌ๋ก๋
};
return (
<Link to="/dashboard" onMouseEnter={handleMouseEnter}>
๋์๋ณด๋
</Link>
);
};