JavaScript
$ npm install react-router-dom
TypeScript
$ npm i @types/react-router-dom
이 컴포넌트는 웹 애플리케이션에 HTML5의 History API를 사용하여 페이지를 새로 불러오지 않고도 주소를 변경하고 현재 주소의 경로에 관련된 정보를 리액트 컴포넌트에서 사용할 수 있도록 해 줍니다.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
이제 리액트 라우터를 통해 여러 페이지로 구성된 웹 애플리케이션을 만들기 위하여 각 페이지에서 사용할 컴포넌트를 만들 차례이다.
가장 먼저 보여지게 될 Home 페이지 컴포넌트 와 웹 사이트를 소개하는 About 페이지 컴포넌트 생성
// src/pages/Home.jsx
const Home = () => {
return (
<div>
<h1>홈</h1>
<p>가장 먼저 보여지는 페이지입니다.</p>
</div>
);
};
export default Home;
// src/pages/About.jsx
const About = () => {
return (
<div>
<h1>소개</h1>
<p>리액트 라우터를 사용해 보는 프로젝트입니다.</p>
</div>
);
};
export default About;
사용자의 브라우저 주소 경로에 따라 우리가 원하는 컴포넌트를 보여주기 위해서 Route 라는 컴포넌트 사용
Routes 라는 컴포넌트 안에 Route 컴포넌트 사용
<Route path="주소규칙" element={보여 줄 컴포넌트 JSX} />
import { Route, Routes } from 'react-router-dom';
import About from './pages/About';
import Home from './pages/Home';
const App = () => {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
};
export default App;
Link : 다른 페이지로 이동하는 링크
=> a태그를 바로사용하면 안됨, 페이지를 새로 불러오는 것을 막고 History API를 통해 주소의 경로만 바꾸는 기능이 내장되어 있어서
a 태그 : 페이지를 이동할 때 브라우저에서는 페이지를 새로 불러온다
<Link to="경로">링크 이름</Link>
// src/pages/Home.jsx
import { Link } from 'react-router-dom';
const Home = () => {
return (
<div>
<h1>홈</h1>
<p>가장 먼저 보여지는 페이지입니다.</p>
<Link to="/about">소개</Link>
</div>
);
};
export default Home;
페이지 주소를 정의할 때 유동적인 값을 사용해야 할 때
- URL 파라미터는 주소의 경로에 유동적인 값을 넣는 형태
=> (ID 또는 이름을 사용하여 특정 데이터를 조회할 때 사용)
- 쿼리 스트링은 주소의 뒷부분에 ?문자열 이후에 key=value로 값을 정의하며 &로 구분하는 형태
=> 키워드 검색, 페이지네이션, 정렬 방식 등 데이터 조회에 필요한 옵션을 전달할 떄 사용
src/App.js
import React from 'react'; import './style.css'; import { Route, Routes } from 'react-router-dom'; import { Home, About, Profile } from './pages'; const App = () => { return ( <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> <Route path="/profiles/:username" element={<Profile />} /> </Routes> ); }; export default App;
URL 파라미터는 /profiles/:username 과 같이 경로에 : 를 사용하여 설정합니다
src/pages/Home.jsx
import React from 'react'; 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/minseok">Minseok의 프로필</Link> </li> <li> <Link to="/profiles/void">존재하지 않는 프로필</Link> </li> </ul> </div> ); }; export default Home;
src/pages/Profile.jsx
import React from 'react'; import { useParams } from 'react-router-dom'; const data = { minseok: { name: '오민석', description: '프론트엔드 개발자', }, }; const Profile = () => { const params = useParams(); const profile = data[params.username]; return ( <div> <h1>사용자 프로필</h1> {profile ? ( <div> <h2>{profile.name}</h2> <p>{profile.description}</p> </div> ) : ( <p>존재하지 않는 프로필입니다.</p> )} </div> ); }; export default Profile;
src/pages/About.jsx
import { useLocation } from 'react-router-dom'; const About = () => { const location = useLocation(); return ( <div> <h1>소개</h1> <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p> <p>쿼리스트링: {location.search}</p> </div> ); }; export default About;
useLocation 이라는 Hook을 사용했는데 location 객체를 반환하며 이 객체는 현재 사용자가 보고있는 페이지의 정보를 지니고 있다
쿼리스트링을 따로 파싱까지 해야된다면 번거로울수도 있는데, v6부터 useSearchParams 라는 Hook을 통해서 쿼리스트링을 다룰 수 있다.
다음은 이 Hook을 사용하여 쿼리스트링을 쉽게 파싱하여 사용하는 예시입니다.
src/pages/About.js
import { useSearchParams } from 'react-router-dom'; const About = () => { const [searchParams, setSearchParams] = useSearchParams(); const detail = searchParams.get('detail'); const mode = searchParams.get('mode'); const onToggleDetail = () => { setSearchParams({ mode, detail: detail === 'true' ? false : true }); }; const onIncreaseMode = () => { const nextMode = mode === null ? 1 : parseInt(mode) + 1; setSearchParams({ mode: nextMode, detail }); }; return ( <div> <h1>소개</h1> <p>리액트 라우터를 사용해 보는 프로젝트입니다.</p> <p>detail: {detail}</p> <p>mode: {mode}</p> <button onClick={onToggleDetail}>Toggle detail</button> <button onClick={onIncreaseMode}>mode + 1</button> </div> ); }; export default About;
주의점
쿼리파라미터를 조회할 때 값은 무조건 문자열 타입이라는 것 입니다. 즉, true 또는 false 값을 넣게 된다면 값을 비교할 때 꼭 'true' 와 같이 따옴표로 감싸서 비교를 하셔야 하고, 숫자를 다루게 된다면 parseInt 를 사용하여 숫자 타입으로 변환을 해야 한다.