안녕하세요. 이번에는 react-router-dom을 이용하는 과정에서 header와 footer를 놓는 방법을 소개하려고 합니다.
과거 프로젝트를 rebuilding하던 와중 react-router-dom을 lastest download 했는데 좀 새롭게 바뀌었더군요. 요즘 Nextjs 위주로 프로젝트 하다가 react-router-dom을 이용한 route를 하려니 약간 불편하였습니다. 신박하기도 했구요. 그래서 글로 정리해보려고 합니다.
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<BrowserRouter>
<RecoilRoot>
<App />
</RecoilRoot>
</BrowserRouter>
</Provider>
);
return (
<div className="App">
<Header/>
<Routes>
<>
<Route path="/" element={<Home />}/>
<Route path="/detail/:id" element={<Detail/>}></Route>
</>
</Routes>
</div>
);
이런식으로 작성하면 Header는 고정된 상태로 "/"이나 "/detail/:id" 진입했었습니다. 그런데 이것은 예전 방식이 되어버린 것이죠.
길게 끌거 없이 바로 본론으로 넘어가봅시다.
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Route, RouterProvider, createBrowserRouter, createRoutesFromElements } from 'react-router-dom';
import Login from './pages/Login';
import NavBar from './components/NavBar';
import Home from './components/Home';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
const router = createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<App />}>
<Route path="/" element={<Home />}/>
<Route path="/login" element={<Login />}/>
</Route>
)
)
root.render(
<React.StrictMode>
<RouterProvider router={router}/>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
먼저 index.tsx를 다음과 같이 작성합니다.
참고 : 공식문서
여기서 중요한 것은
<Route path="/" element={<App />}>
와 같이 parent route elements가
<Route path="/" element={<Home />}/>
<Route path="/login" element={<Login />}/>
child route elements를 가져야 한다는 것입니다.
이것이 중요한 이유는 Outlet을 통해 Header와 Footer는 child route가 rendering될 때 중첩될 수 있도록 만들기 때문입니다.
import { Outlet } from "react-router-dom";
import NavBar from "./NavBar";
import Footer from "./Footer";
export default function App() {
return (
<div className="flex flex-col h-screen">
<NavBar />
<Outlet />
<Footer />
</div>
);
}
여기서 중요한 것은 Outlet입니다.
아까 위에서 제가 언급했듯이 parent route elements와 child route elements개념에 따라 App.tsx인 parent route elements가 "/"에서 rendering되고 그 이후에 child route elements인 home이나 Login이 각각 "/", "/login"에서 rendering될 때 Outlet 자리에 Home이나 Login component가 들어가게 되어 NavBar와 Footer가 항상 중첩되어 보일 수 있게 되는 것입니다.
참고 : 공식문서
지속적인 libray update에 따라 다시 해당 library를 공부해야 함이 다소 번거롭다고 생각은 들지만, 학습을 했을 때 즐거움이 있기에 힘들어도 앞으로 나아갈 수 있는 것 같습니다.
이 글을 보시고 피드백이 필요한 부분이나 더 간단한 방법을 아시는 분들은 댓글 남겨주시기 바랍니다. 감사합니다.