
TypeScript & React 환경에서 Router를 사용하는 방법에 대해 포스팅 해보려고 한다.
우선 타입 스크립트를 사용한다고 하더라도 router를 사용하는 것에 있어서 크게 다를 것은 없지만 일부 기능들은 타입을 지정해줘야 사용할 수가 있다.
대표적으로 history, location, match가 있는데 이들을 제외한 나머지는 사용방법이 동일하다.
react router v6 를 기준으로 포스팅하겠다.
$ npm install react-router react-router-dom
$ npm install -D @types/react-router @types/react-router-dom
import React from 'react';
import Header from './components/Header';
import Footer from './components/Footer';
import MainPage from './pages/MainPage';
import LoginPage from './pages/LoginPage';
import { BrowserRouter, Route, Routes, Link } from 'react-router-dom';
const App: React.FC = () => {
return (
<>
<BrowserRouter>
<Header></Header>
<Routes>
<Route path='/' element={<MainPage />}></Route>
<Route path='/login' element={<LoginPage />}></Route>
</Routes>
</BrowserRouter>
<Footer></Footer>
</>
);
};
export default App;
취향에 따라 index.tsx 나 App.tsx에 <BrowserRouter></BrowserRouter>를 사용할 수 있다.
React-Router-Dom 이 제공하는 컴포넌트이다.
<a href=#> 로 보인다.추가적으로
Link 컴포넌트와<a>의 차이점은?
<a href=#>는 전체 페이지를 재렌더링 시킨다. 브라우저 주소를 이동하고 페이지 자체를 새로고침한다. 따라서 상태 값이 유지되지 못하고 속도도 저하된다.
그러므로 외부 프로젝트와 연결 할 때 주로 사용한다.
<Link />는 SPA의 특징에 맞게 필요한 부분만 재렌더링하고 나머지 부분은 그대로 유지된다. 데이터를 필요한 부분만 불러올 수 있기 때문에 속도향상에 도움이된다.
그러므로 프로젝트 내에서 페이지 전환하는 경우 사용한다.
// Router.js
function Router() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Login />} />
<Route path="/main" element={<Main />} />
</Routes>
</BrowserRouter>
);
}
export default Router;
// Login.js
import React from "react";
import { Link } from "react-router-dom";
function Login() {
return (
<div>
<Link to="/signup">회원가입</Link>
</div>
);
}
export default Login;
여러가지가 있지만 기본적으로 살펴볼 내용만 보자!
import { useParams, useLocation, useNavigate, useMatch } from 'react-router';
리액트에서 라우터 사용 시 파라미터 정보를 가져와 활용하고 싶다면 useParams라는 훅을 사용하면 된다.
(파라미터는 일반적으로 특정 아이디 또는 이름을 사용하여 조회할 때 사용된다.)
URL에 포함되어있는 Key, Value 형식의 객체를 반환해주는 역할을 한다.
파라미터가 아닌 현재 페이지의 Pathname이나 쿼리를 가져오려면 useLocation()을 사용해야 한다.
...URL/user/1
user는 pathname, 1은 parameter
사용법
//App.tsx부분
<Routes>
<Route path='/artist/:groupId' element={<ArtistPage />} />
</Routes>
//useParams를 사용하는 tsx부분
//import해오기
//artist.tsx
import { useParams } from 'react-router-dom';
const ArtistPage = () => {
//Route의 path와 이름을 맞춰줘야 한다.
const { groupId } = useParams();
:id와 같이 path를 주더라도 절대 number형이 아니므로 주의하자useNavigate 훅을 실행하면 페이지 이동을 할 수 있게 해주는 함수를 반환한다.
조건이 필요한 곳에서 navigate 함수를 호출해서 경로를 이동할 수 있다.
(참고로 v5버전에서의 history 기능을 대체할 수 있다.)
사용 예)
import { useNavigate } from "react-router-dom";
const Login = () => {
const navigate = useNavigate();
return(
<div className="login">
<input placeholder="전화번호, 사용자 이름 또는 이메일"/>
<input placeholder="비밀번호/>
<button onClick={() => {navigate("/main");}}>로그인</button>
</div>
)
}
추가적으로
Link 컴포넌트와 useNavigate hook의 차이?
1. Link
- 클릭 시 바로 이동하는 로직 구현 시에 사용
ex) 상품 리스트에서 상세 페이지 이동 시
- useNavigate
- 페이지 전환 시 추가로 처리해야 하는 로직이 있을 경우 useNavigate 사용
ex) 로그인 버튼 클릭 시
회원가입 되어 있는 사용자 -> Main 페이지로 이동
회원가입이 되어 있지 않은 사용자 -> SignUp 페이지로 이동
1번 useParams에서 설명했듯 파라미터가 아닌
pathname이나 쿼리를 사용하려면 useLocation 훅을 사용한다.
이 훅은 location 객체를 반환한다.
이때 pathname 에서 pathname을
search 에서는 쿼리를 획득할 수 있다
사용 예)
import React from 'react';
import styled from 'styled-components';
import { useParams, useLocation, useNavigate, useMatch } from 'react-router';
const LoginPageContainer = styled.div``;
const LoginPage = () => {
const location = useLocation();
console.log(location);
return (
<LoginPageContainer>
<h1> 로그인 페이지 </h1>
</LoginPageContainer>
);
};
export default LoginPage;

추가적으로 사용 예시를 하나 더 살펴보자
만약 http://경로?id=10&count=2022로 접속한 경우 쿼리를 획득하려면?
import React from 'react';
import { useLocation } from 'react-router-dom';
// http://localhost:3000/query?id=10&count=2022 로 접속 상황
function Query() {
// useLocation() 호출
const location = useLocation();
console.log(location);
// {pathname: '/query', search: '?id=10&count=2022', hash: '', state: null, key: 'default'}
// search 부분을 URLSearchParams 객체로 생성
const searchParams = new URLSearchParams(location.search);
// const searchParams = new URLSearchParams(useLocation().search); // 이것도 가능
// 쿼리 취득
const id = searchParams.get('id'); // id 취득
const count = searchParams.get('count'); // count 취득
console.log('id: ', id); // id: 10
console.log('count: ', count); // count: 2022
return <div>Query</div>;
}
export default Query;

React-Router v5의 useRouterMatch가 v6로 넘어오면서 useMatch로 변경되었다.
useMatch()의 인자로 url을 넘기면 해당 url과 일치할 경우 url의 정보를 반환하고, 일치하지 않을 경우 null을 반환한다.
예시
여러 개의 탭 중 현재 보여지고 있는 탭에만 accent color를 줄 경우
import { useMatch } from "react-router-dom";
import styled from "styled-components";
const Tab = styled.span<{ isActive: boolean }>`
color: ${(props) =>
props.isActive ? props.theme.accentColor : props.theme.textColor};
`;
const Coin = () => {
const matchPriceTab = useMatch("/:coinId/price");
const matchChartTab = useMatch("/:coinId/chart");
return (
<Tab isActive={matchPriceTab !== null}>
<Link to={`/${coinId}/price`}>Price</Link>
</Tab>
<Tab isActive={matchChartTab !== null}>
<Link to={`/${coinId}/chart`}>Chart</Link>
</Tab>
)
}
일치하면

일치 하지 않으면
null