## Browser Router - react-router-dom에서 `Routes`와 `Route` 를 통해 경로를 지정할 수 있다. ```jsx import { BrowserRouter, Route, Routes } from "react-router-dom"; import About from "./screens/About"; import Home from "./screens/Home"; import Header from "./components/Header"; function Router() { return ( <BrowserRouter> <Header /> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </BrowserRouter> ); } ``` ## Create Browser Router - **Browser Router**보다 좀 더 선언적(?)으로 바꿔준다. - 기존의 방식은 `App()`에서 Router들을 **Render**하였지만 **Create Browser Router는 Router**를 Array 형식으로 표현한다. - Array 안에는 각각의 요소가 **Path, Element, Children** 값을 가진다. - **Path** : 경로 - **Element** : 해당 경로에 일치하면 불러올 Components - **Children** : Path의 하위 페이지 자식들 ```jsx import { createBrowserRouter } from "react-router-dom"; import About from "./screens/About"; import Home from "./screens/Home"; import Root from "./Root"; const router = createBrowserRouter([ { path: "/", element: <Root />, children: [ { path: "", element: <Home />, }, { path: "about", element: <About />, }, ], }, ]); export default router; ``` - Children의 요소들은 Parent에서 불러오기 때문에 해당 Children을 띄울 위치를 지정해주어야 한다. - **Outlet**를 통해 Children Component를 띄울 위치를 지정해주면 된다. 이를 통해 공통 **Components(Header, SideBar, Footer)**를 쉽게 공유할 수 있다. ```jsx import { Outlet } from "react-router-dom"; import Header from "./components/Header"; function Root() { return ( <div> <Header /> <Outlet /> </div> ); } export default Root; ``` 💡 `App()`에서는 RouterProvider를 통해 사용할 Create Browser Router를 지정해주어야 한다. > ```jsx > import { RouterProvider } from 'react-router-dom'; > > function App() { > return ( > <Container> > <RouterProvider router={router} /> > </Container> > ); > } > ``` ## Error Element - **ErrorElement**를 통해 Page에서 일어나는 각종 **Errors**를 **Handle** 할 수 있다. - 각 요소의 **errorElement** 추가해 해당 Page에서 오류가 발생 시 Render 할 Component를 지정할 수 있다. - **Errors**를 **Handle**하게 되면 특정 Page에서 오류가 발생하게 되더라도 다른 Page는 동작한다. ```jsx import NotFound from "./screens/NotFound"; import ErrorComponent from "./screens/ErrorComponent"; const router = createBrowserRouter([ { path: "/", element: <Root />, children: [ { path: "", element: <Home />, errorElement: <ErrorComponent />, }, { path: "about", element: <About />, }, ], errorElement: <NotFound />, }, ]); ``` ## UseParams - (Create Browser Router) - Create Browser Router에서 Parameter를 넘겨주기 위해서는 **Path**안에 해당 값을 `:` 으로 명시해주어야 한다. ```jsx const router = createBrowserRouter([ { path: "/", element: <Root />, children: [ { path: "", element: <Home />, errorElement: <ErrorComponent />, }, { path: "about", element: <About />, }, { path: "users/:userId", element: <Users />, }, ], errorElement: <NotFound />, }, ]); ``` 💡 해당 경로를 통해 얻은 Parameter는 useParam을 통해 값을 받을 수 있다. > ```tsx > import { users } from "../../db"; > function Users() { > const { userId } = useParams(); > return <div>Users {userId} is named : {users[Number(userId) - 1].name}</div>; > } > ``` ## Outlet - **Create Browser Router**에서 부모 요소가 자식 요소로 이동할 때는 **절대 경로**가 아닌 **상대 경로**로 이동하면 된다. ```jsx function Users() { const { userId } = useParams(); return <div>Users {userId} is named : {users[Number(userId) - 1].name} <hr /> <Link to="followers">See followers</Link> /* '/'를 빼면 상대경로이다. */ <Outlet /> </div>; } ``` - 만약 부모 요소에서 자식 요소로 값을 보내고 싶을 때는 **Outlet**에서 **context**를 통해 **해당 값을 넘겨주면 된다. ```jsx function Users() { const { userId } = useParams(); return <div> <h1> Users {userId} is named : {users[Number(userId) - 1].name} </h1> <hr /> <Link to="followers">See followers</Link> <Outlet context={{ nameOfMyUser: users[Number(userId) - 1].name, }} /> /* nameOfMyUser 값을 모든 Children에게 넘긴다. */ </div>; } ``` - **Children**은 해당 값읋 **useOutletContext**를 통해서 전달 받을 수 있다. - 이때 당연히 TS를 사용하고 있다면 전달 받는 데이터의 **Type**을 지정해주어야 한다. ```tsx import { useOutletContext } from "react-router-dom"; interface FollowersContextType { nameOfMyUser: string; } function Followers() { const { nameOfMyUser } = useOutletContext<FollowersContextType>(); return <h1>Here are {nameOfMyUser}'s followers</h1>; } export default Followers; ``` ## useSearchParams - **useSearchParams Hook**을 사용해서 Search Parameter를 가져오거나 변경할 수 있다. - **readSearchParams** : has, get 등 여러 함수를 통해 데이터를 있는지 파악하거나 가져올 수 있다. - **setReadSearchParams** : Search Parameter를 직접 설정 할 수 있다. ```jsx function Home() { const [readSearchParams, setReadSearchParams] = useSearchParams(); setTimeout(() => { setReadSearchParams({ day: "today", tomorrow: "123", }); }, 1000); console.log(readSearchParams.get("day")); return <div> <ul> {users.map((user) => ( <li key={user.id}> <Link to={`/users/${user.id}`}>{user.name}</Link> </li> ))} </ul> </div>; } ```