ํ์ต ํค์๋
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์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์์ด์!');
});
});
});
๐ ์ฐธ๊ณ