안녕하세요, 코린이의 코딩 학습기 채니 입니다.
[리액트를 다루는 기술]의 책을 참고하여 포스팅한 개인 공부 내용입니다.
리액트 라우터로 SPA 개발하기
중첩된 라우트
Articles.js
import { Link } from 'react-router-dom'
const Articles = () => {
return(
<ul>
<li>
<Link to="/articles/1">게시글 1</Link>
</li>
<li>
<Link to="/articles/2">게시글 2</Link>
</li>
<li>
<Link to="/articles/3">게시글 3</Link>
</li>
</ul>
)
}
export default Articles;
Article.js
import { useParams } from "react-router-dom";
const Article = () => {
const { id } = useParams();
return (
<div>
<h2>게시글 {id}</h2>
</div>
)
}
export default Article;
useParams Hook을 이용해 파라미터 이름을 가져왔습니다.
App.js
import './App.css';
import Home from './pages/Home';
import About from './pages/About';
import { Routes, Route } from 'react-router-dom';
import Profile from './pages/Profile';
import Articles from './pages/Articles';
import Article from './pages/Article';
function App() {
return (
<Routes>
<Route path='/' element={<Home />} />
<Route path='/about' element={<About />} />
<Route path='/profiles/:username' element={<Profile />} />
<Route path='/articles' element={<Articles />} />
<Route path='/articles/:id' element={<Article />} />
</Routes>
);
}
export default App;
해당 페이지들의 Route 설정을 해줍니다.
Home.js
import { Link } from 'react-router-dom';
const Home = () => {
return (
<div>
<h1>홈</h1>
<p>가장 먼저 보여지는 페이지입니다.</p>
<ul>
<li>
<Link to="/about">소개</Link>
</li>
<li>
<Link to="/profiles/chany">chany의 프로필</Link>
</li>
<li>
<Link to="/profiles/gildong">gildong의 프로필</Link>
</li>
<li>
<Link to="/profiles/void">존재하지 않는 프로필</Link>
</li>
<li>
<Link to="/articles">게시글 목록</Link>
</li>
</ul>
</div>
)
}
export default Home;
게시글 목록 페이지로 이동할 수 있도록 Home.js에 Link를 걸어줍니다.
이동도 잘 되고 출력도 잘 되는 것을 확인할 수 있습니다.
만일 각 게시글 하단에 게시글 목록을 표시해줘야한다면 어떻게 해아할까요?
ArticleList 컴포넌트를 새로 만들어 렌더링 해줄 수도 있지만, 중첩 라우트를 사용해 렌더링해줄 수도 있습니다.
App.js
import './App.css';
import Home from './pages/Home';
import About from './pages/About';
import { Routes, Route } from 'react-router-dom';
import Profile from './pages/Profile';
import Articles from './pages/Articles';
import Article from './pages/Article';
function App() {
return (
<Routes>
<Route path='/' element={<Home />} />
<Route path='/about' element={<About />} />
<Route path='/profiles/:username' element={<Profile />} />
{/* 수정 */}
<Route path='/articles' element={<Articles />} >
<Route path=':id' element={<Article />} />
</Route>
</Routes>
);
}
export default App;
Articles.js
import { Link, Outlet } from 'react-router-dom'
const Articles = () => {
return(
<div>
<Outlet />
<ul>
<li>
<Link to="/articles/1">게시글 1</Link>
</li>
<li>
<Link to="/articles/2">게시글 2</Link>
</li>
<li>
<Link to="/articles/3">게시글 3</Link>
</li>
</ul>
</div>
)
}
export default Articles;
Outlet 컴포넌트
- Route의 children으로 들어가는 JSX 엘리먼트를 보여주는 역할
Outlet 컴포넌트를 이용하여 Articles Route의 children인 Article를 보여주어 쉽게 처리할 수 있습니다.
공통 레이아웃 컴포넌트
이러한 Outlet 컴포넌트 속성을 이용하여 공통적으로 보여줘야 하는 레이아웃 또한 쉽게 보여줄 수 있습니다.
Layout.js
import { Outlet } from "react-router-dom";
// 헤더 레이아웃
const Layout = () => {
return (
<div>
<header style={{background: 'lightgray', padding: 16, fontSize: 24}}>
Header
</header>
<main>
<Outlet />
</main>
</div>
)
}
export default Layout;
App.js
import './App.css';
import Home from './pages/Home';
import About from './pages/About';
import { Routes, Route } from 'react-router-dom';
import Profile from './pages/Profile';
import Articles from './pages/Articles';
import Article from './pages/Article';
import Layout from './Layout';
function App() {
return (
<Routes>
<Route element={<Layout />}>
<Route path='/' element={<Home />} />
<Route path='/about' element={<About />} />
<Route path='/profiles/:username' element={<Profile />} />
</Route>
<Route path='/articles' element={<Articles />} >
<Route path=':id' element={<Article />} />
</Route>
</Routes>
);
}
export default App;
Home, About, Profile 컴포넌트에는 Header가 표시되도록 하였습니다.
따라서 해당 라우트들을 Layout 라우트와 중첩 시킨 후 Layout 컴포넌트에서 이들을 Outlet으로 표시해주었습니다.
index props
index props는 'path="/''와 동일한 의미를 가집니다.
App.js
function App() {
return (
<Routes>
<Route path='/' element={<Layout />}>
<Route index element={<Home />} /
...
...
Home Route 컴포넌트를 path 대신 index로 표시해주었지만, '/' 경로에 들어가도 여전히 잘 표시됩니다.
상위 라우트의 경로와 일치하지만, 이후 경로가 주어지지 않았을 때 보여지는 라우트를 설정해주는 것이죠.
path="/"와 동일한 역할을 하지만 좀 더 명시적으로 표현하는 방법입니다.