react-router-dom의 BrowserRouter, Routes, Route, Link 컴포넌트를 사용한다.
// Router.tsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './Components/Header';
import Home from './pages/Home';
import About from './pages/About';
function Router() {
return (
<BrowserRouter>
<Header />
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
</BrowserRouter>
);
}
export default Router;
Link 컴포넌트 역시 BrowserRouter에 포함되어야 하며, to={path}가 가리키는 경로로 url이 바뀌며 위 라우터가 동작한다.
// Header.tsx
import { Link } from 'react-router-dom';
function Header() {
return (
<header>
<h1>Hello, Router</h1>
<nav>
<ul>
<li>
<Link to={'/'}>Home</Link>
</li>
<li>
<Link to={'/about'}>About</Link>
</li>
</ul>
</nav>
</header>
);
}
export default Header;
<BrowserRout>로 감싸지 않고 RouterRrovider를 사용하는데 router={} props를 필수로 넣어야 한다.
Router.tsx에서 createBrowserRouter 함수로 생성한 router를 넘겨준다.
// index.tsx
import { RouterProvider } from 'react-router-dom';
import router from './Router';
root.render(
<React.StrictMode>
<RouterProvider router={router} />
</React.StrictMode>,
);
createBrowserRouter()에 라우팅 할 path와 element로 작성할 수 있다.
children 속성으로 배열에 중첩된 라우터를 추가할 수 있다.
// Router.tsx
import { createBrowserRouter } from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';
import App from './App';
const router = createBrowserRouter([
{
path: "/", // "/" -> 부모
element: <Root />, // Root의 자식들을 render
children: [
{
path: "",
element: <Home />,
errorElement: <ErrorComponent />, // 레이아웃은 그대로 유지하면서 에러 컴포넌트를 보여준다
},
{
path: "about",
element: <About />,
},
{
path: "users/:userId",
element: <User />,
children: [
{
path: "followers",
element: <Followers />
},
],
},
],
errorElement: <Notfound />,
},
])
export default router;
하위 경로에 알맞는 컴포넌트를 출력하기 위해서 App.tsx에 <Outlet /> 을 추가한다.
<Header /> : 고정영역
<Outlet /> : render하고 싶은 route로 바꿔서 (자식들을)render해줌, 중첩 라우팅을 이용하여 부모 레이아웃은 그대로 두고 자식 레이아웃만 쉽게 교체할 수 있다.
// App.tsx
import { Outlet } from 'react-router-dom';
import Header from './Components/Header';
function App() {
return (
<div>
<Header />
<Outlet context={{ darkMode: true }} />
</div>
);
}
export default App;
Hook으로 자손 컴포넌트에서 위의 <Outlet />의 context props를 가져오기 위해 사용한다.
// User.tsx
import { Link, Outlet, useOutletContext, useParams } from "react-router-dom";
import { users } from "../db";
function User() {
const { userId } = useParams(); // {userId: '1'}
console.log(useOutletContext()); // {darkMode: true}
return (
<div>
<h1>User with it {userId} is name: {users[Number(userId)-1].name}</h1>
<hr />
<Link to="followers">See followers</Link>
<Outlet
// user의 모든 자식들에게 context 전송
context={{
nameOfMyuser: users[Number(userId)-1].name,
}}
/>
</div>
)
}
// useParams() : Route path 와 일치하는 현재 URL에서 동적 매개변수의 키/값 쌍의 개체를 반환한다.
// 부모 컴포넌트안에 <Outlet content={{}}/>으로 원하는 자손 컴포넌트 위치를 정한다. 그리고 context prop으로 자손 컴포넌트에게에게 넘기고 싶은 값을 넣는다.
export default User;
// Followers.tsx
import { useOutletContext } from "react-router-dom";
interface IFollowersCotext {
nameOfMyuser: string;
}
function Followers() {
//const { userId } = useParams();
//useParams대신 자식 route와 소통하는 방식
const {nameOfMyuser} = useOutletContext<IFollowersCotext>();
return (
<h1>Here are {nameOfMyuser}의 followers</h1>
)
}
export default Followers;