[React] BrowserRouter / createBrowserRouter

hellow_coding·2023년 2월 26일

📌 BrowserRouter

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;

📌 createBrowserRouter

RouterRrovider

<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()

createBrowserRouter()에 라우팅 할 pathelement로 작성할 수 있다.
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;

Outlet

하위 경로에 알맞는 컴포넌트를 출력하기 위해서 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;

useOutletContext

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;
profile
꿈많은 개발자

0개의 댓글