React Router Upgrading
ํ์ต ํค์๋
React Router 6.4
createBrowserRouter
createMemoryRouter
RouterProvider
Outlet
React Router 6.4
React Router ๋ฒ์ 6.4๋ถํฐ ์ง์ํ๋ ๋ผ์ฐํฐ ๊ฐ์ฒด
๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํด๋ณด์.
์๋์ ๊ฐ์ ๋ฐฉ์์ผ๋ก React Router๋ฅผ ์ด์ฉํด์ ๋ผ์ฐํฐ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํด๋ณด์.
import Header from './components/Header';
import Footer from './components/Footer';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
// โฌ๏ธ React Router๋ฅผ ์ด์ฉํด์ ๋ผ์ฐํฐ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด ๋ณด์!
const pages = {
'/': HomePage,
'/about': AboutPage,
};
export default function App() {
const path = window.location.pathname;
const Page = Reflect.get(pages, path) || HomePage;
return (
<div>
<Header />
<main>
<Page />
</main>
<Footer />
</div>
);
}
React Router v6.4 ์ ์ฌ์ฉ๋ฒ
๐ค App ์ปดํฌ๋ํธ์ 2๊ฐ์ง ์ญํ
ํ์ฌ App ์ปดํฌ๋ํธ๋ 2๊ฐ์ง ์ญํ ์ ํ๊ณ ์๋ค. ์ด๋ค ๋ ์ด์์์ ์ทจํ๊ณ ์๋์ง
์ ์ด๋ป๊ฒ ๋ผ์ฐํ
์ด ๋๋์ง
์ด๋ค.
// App.tsx
import { Routes, Route } from 'react-router-dom';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import Header from './components/Header';
import Footer from './components/Footer';
export default function App() {
return (
<div>
<Header />
<main>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
</main>
<Footer />
</div>
);
}
๐ App ์ปดํฌ๋ํธ์์ 2๊ฐ์ง ์ญํ์ ๋ถ๋ฆฌํด๋ณด์
RoutingPage ์ปดํฌ๋ํธ๋ฅผ ์์ฑํด์ ๋ผ์ดํ ๊ณผ ๊ด๋ จ๋๊ฑด ๋๊ฒจ์ฃผ๊ณ , App์ปดํฌ๋ํธ๋ ๋ ์ด์์ ๊ด๋ฆฌํ๋๋ก ๋ถ๋ฆฌ๋์๋ค. ๊ทธ๋ ๋ค๋ฉด RoutingPage ๋ฅผ ๊ฐ์ฒด๋ฐฉ์์ผ๋ก ๋ง๋ค์ด๋ ๋์ง ์์๊น?
import { Routes, Route, createBrowserRouter } from 'react-router-dom';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import Header from './components/Header';
import Footer from './components/Footer';
function RoutingPage() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</Routes>
);
}
export default function App() {
return (
<div>
<Header />
<main>
<RoutingPage />
</main>
<Footer />
</div>
);
}
๐ ๋ผ์ฐํ
์ฒ๋ฆฌ๋ฅผ ๋
๋ฆฝ์ํค์
Route ์ปดํฌ๋ํธ์ path์ element๋ฅผ ๋งตํํ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๋๋ก ํ๋ค.
const routes = [
{path: '/', element: <HomePage />},
{path: '/about', element: <AboutPage />},
];
createBrowserRouter๋ฅผ ์ด์ฉํด์ ๋ผ์ฐํฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์ด๋ ๊ฒ ์์ฑ๋ ๋ผ์ฐํฐ ๊ฐ์ฒด๋ ๋ผ์ฐํ ์ ์ฒ๋ฆฌํ๋๋ฐ ์ฌ์ฉํ๋ค.
const router = createBrowserRouter(routes);
๊ทธ๋ฆฌ๊ณ RouterProvider๋ฅผ ์ด์ฉํด์ router ๊ฐ์ฒด๋ฅผ ์ฐ๊ฒ ๋ค๊ณ ํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด์์ ๋ผ์ฐํ ์ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋๋ค.
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
const routes = [
{ path: '/', element: <HomePage /> },
{ path: '/about', element: <AboutPage /> },
];
const router = createBrowserRouter(routes);
export default function App() {
return (
<RouterProvider router={router}></RouterProvider>
)
}
๋ ์ด์ BrowserRouter๊ฐ ๋ผ์ฐํ ์ ๊ด๋ฆฌํ์ง ์๋๋ค. createBrowserRouter ํจ์์ RouterProvider ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ์ฌ ๋ผ์ฐํ ์ ์ค์ ํ๊ณ ๊ด๋ฆฌํ๋ค. ๋๋ฌธ์ main ์ปดํฌ๋ํธ์์ BrowserRouter ์ปดํฌ๋ํธ๋ ์ ๊ฑฐํ๋ค.
๐ ๋ ์ด์์ ๋
๋ฆฝ ์ํค๊ธฐ
๋ถ๊ธฐ์์ ์ด ์๊ธฐ ๋๋ฌธ์ ์์ ๋ฐฉ์์ฒ๋ผ ์ฌ์ฉํ๋๊ฑด ๋๋ฌด ๋ถํธํ๋ค. ๋ ์ด์์ ์์ฒด๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ปดํฌ๋ํธ๋ก ๋ ๋ฆฝ์ํจ๋ค.
function Layout() {
return (
<div>
<Header />
<main>
{/* <RoutingPage /> */}
<Outlet />
</main>
<Footer />
</div>
);
}
routesํํ
Layout ์ปดํฌ๋ํธ์ ์ ์ฉํ๋ค๋ ๊ฒ์ ์ก์์ค์ผ ํ๋ค. ๊ทธ๋ ค์ง๋ ๊ฒ์ ๋ชจ๋ <Layout />
์ผ๋ก ๊ทธ๋ ค์ง๋๋ก ํด์ผ ํ๋ค.
์ด๋ฅผ ์ํด์ routes๋ฅผ ๊ณ์ธตํ์ผ๋ก ๋ฐ๊พธ์๋ค.
const routes = [
{
element: <Layout />,
children: [
{ path: '/', element: <HomePage /> },
{ path: '/about', element: <AboutPage /> },
],
},
];
๋ค๋ง Layout ์ปดํฌ๋ํธ๊ฐ HomePage ์ปดํฌ๋ํธ์ AboutPage ์ปดํฌ๋ํธ๋ฅผ ์ธ์งํด์ ์ฌ๋ฐ๋ฅธ ์์น์ ๋ฃ์ด์ผ ํ๋ค. ์ด๋ React Router๊ฐ ์ง์ํ๋ ์ปดํฌ๋ํธ์ธ Outlet ์ ์ฐ๋ฉด๋๋ค.
Outlet ์ปดํฌ๋ํธ๋ Layout ์ปดํฌ๋ํธ ์์ ์ ์๋ ๋ ์ด์์ ๊ตฌ์กฐ๋ฅผ ๊ทธ๋๋ก ์ ์งํ๋ฉด์ ์ปดํฌ๋ํธ๋ฅผ ๋์ ์ผ๋ก ๋ ๋๋ง ํ ์ ์๋ค.
import { createBrowserRouter, RouterProvider, Outlet } from 'react-router-dom';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import Header from './components/Header';
import Footer from './components/Footer';
function Layout() {
return (
<div>
<Header />
<main>
<Outlet />
</main>
<Footer />
</div>
);
}
const routes = [
{
element: <Layout />,
children: [
{ path: '/', element: <HomePage /> },
{ path: '/about', element: <AboutPage /> },
],
},
];
const router = createBrowserRouter(routes);
export default function App() {
return <RouterProvider router={router}></RouterProvider>;
}
๐ ํ์ผ๋ก ๋ถ๋ฆฌํ์
routes๋ ํ ์คํธ ๋ ํ์ํ ์ ๋ณด์ด๋ค. ๊ทธ๋์ App.tsx ํ์ผ์์ ๋ถ๋ฆฌํ๋๊ฒ ๊ฐ์ ธ๋ค์ฐ๊ธฐ์ ์ข๋ค.
- src
- components
- Footer.tsx
- Header.tsx
- Layout.tsx โ
- pages
- AboutPage.tsx
- HomePage.tsx
- App.tsx
- main.tsx
- routes.tsx โ
๐ง App ์ปดํฌ๋ํธ๋ ํ ์ผ์ด ์๋ค?
App ์ปดํฌ๋ํธ๊ฐ ํ๋ ์ผ์ด ์ค์๋ค. ์ด ์ผ์ main ์ปดํฌ๋ํธ์ ๋ณด๋ด๋ ๋๋ ์ผ์ด๋ผ์ App ์ปดํฌ๋ํธ๊ฐ ํ์ ์์ด์ก๋ค.
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import routes from './routes';
const router = createBrowserRouter(routes);
export default function App() {
return <RouterProvider router={router}></RouterProvider>;
}
๐ ๏ธ ๋ผ์ฐํ
ํ
์คํธ ํ๊ธฐ
์ด์ ์๋ App.test.tsx๋ก App ์ปดํฌ๋ํธ๋ฅผ ํ ์คํธํ๋ค. ์ด์ ๋ routes๊ฐ ์ปดํฌ๋ํธ์ ๋ ์ด์์์ ๋ํ ์ ๋ณด๋ฅผ ๋ชจ๋ ๋ค๊ณ ์๋ค. ๋๋ฌธ์ routes๋ง ํ ์คํธ ํ๋ฉด ๋๋ค.
MemoryRouter
๋ ์ฃผ์๋ฅผ ๊ฐ์ง๊ณ ์์ง ์์, ์ฃผ์๋ฅผ ๋ฐ๋ก ์ก์ ์ค ๊ฒ์ฒ๋ผ createMemoryRouter๋ฅผ ์ฌ์ฉํด์ ํ
์คํธ ํ๋ค.
// App.test.tsx โ routes.test.tsx
import { render, screen } from '@testing-library/react';
import { createMemoryRouter, RouterProvider } from 'react-router-dom';
import routes from './routes';
const context = describe;
describe('App', () => {
function renderRouter(path: string) {
const router = createMemoryRouter(routes, { initialEntries: [path] });
render(<RouterProvider router={router} />);
}
context('when the current path is โ/โ', () => {
it('renders the home page', () => {
renderRouter('/');
screen.getByText(/ํ์/);
});
});
context('when the current path is โ/aboutโ', () => {
it('renders the about page', () => {
renderRouter('/about');
screen.getByText('about์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ด์!');
});
});
});
๐ ์ฐธ๊ณ
Last updated