useHistory()
react-router-dom의useHistory()(v5 기준)는 브라우저의 history stack을 제어할 수 있게 해주는 Hook입니다.
실전에서 자주 사용하는 메서드들 중심으로 핵심만 정리드릴게요.
history.push(path)import { useHistory } from "react-router-dom";
const MyComponent = () => {
const history = useHistory();
const handleClick = () => {
history.push("/detail/123");
};
return <button onClick={handleClick}>상세페이지로 이동</button>;
};
history.replace(path)push()와 달리 히스토리 기록을 덮어씀history.replace("/login"); // 현재 페이지 기록을 로그인 페이지로 덮음
history.go(n)n값만큼 히스토리를 앞이나 뒤로 이동n > 0: 앞으로n < 0: 뒤로history.go(-1); // 뒤로가기
history.go(2); // 앞으로 두 페이지
history.goBack()history.go(-1)과 동일, 뒤로 한 페이지const handleBack = () => {
history.goBack();
};
history.goForward()history.go(1)과 동일, 앞으로 한 페이지const handleForward = () => {
history.goForward();
};
history.locationpathname, search, hash 등 포함)console.log(history.location.pathname); // "/detail/123"
console.log(history.location.search); // "?query=abc"
| 메서드 | 사용 빈도 | 사용 용도 예시 |
|---|---|---|
push(path) | 🔥 매우 자주 | 페이지 이동 (ex. 버튼 클릭 시) |
replace(path) | 👍 중간 | 로그인 등 되돌리기 막을 때 |
goBack() | 🔥 매우 자주 | "<- 뒤로가기" 버튼 구현 |
useNavigate()
react-router-dom v6에서는 기존useHistory()대신useNavigate()훅을 사용합니다.
기능은 거의 같지만, 메서드 형태와 사용 방식이 조금 다릅니다.
const navigate = useNavigate()import { useNavigate } from "react-router-dom";
const MyComponent = () => {
const navigate = useNavigate();
const goToDetail = () => {
navigate("/detail/123");
};
return <button onClick={goToDetail}>상세 페이지로 이동</button>;
};
navigate(path)history.push()와 동일, 경로를 히스토리에 추가하며 이동navigate("/home"); // 홈으로 이동
navigate(path, { replace: true })history.replace()처럼 히스토리를 덮어쓰기navigate("/login", { replace: true });
if (isLoggedIn) {
navigate("/dashboard", { replace: true });
}
navigate(-1)goBack()과 같음. 이전 페이지로 이동navigate(-1); // 뒤로가기
navigate(1); // 앞으로 가기
useNavigate() 자체는 location 정보가 없어요.useLocation() 사용:import { useLocation } from "react-router-dom";
const location = useLocation();
console.log(location.pathname); // 현재 경로
console.log(location.search); // 쿼리스트링
useNavigate()에서 자주 쓰는 패턴| 메서드 | 설명 | 예시 코드 |
|---|---|---|
navigate("/path") | 페이지 이동 | navigate("/home") |
navigate("/path", { replace }) | 현재 페이지 덮어쓰기 (뒤로가기 X) | navigate("/login", { replace: true }) |
navigate(-1) | 브라우저 뒤로가기 | navigate(-1) |
| 기능 | v5 (useHistory) | v6 (useNavigate) |
|---|---|---|
| 이동 | history.push("/path") | navigate("/path") |
| 덮어쓰기 이동 | history.replace("/path") | navigate("/path", { replace: true }) |
| 뒤로가기 | history.goBack() | navigate(-1) |
| 앞으로 가기 | history.goForward() | navigate(1) |
| 현재 경로 확인 | history.location | useLocation() 사용 필요 |
Link & 쿼리스트링 처리법
react-router-dom에서 경로 이동용Link컴포넌트 사용법과
**쿼리스트링 처리법 (?id=123)**을 v5 / v6 기준 모두 비교
Link 컴포넌트 사용법<a href=""> 대신 사용하는 리액트 전용 링크입니다.
페이지를 새로고침하지 않고 경로만 바꿔줍니다.
import { Link } from "react-router-dom";
<Link to="/about">About</Link>
<Link to={`/detail/${id}`}>상세 보기</Link>
<Link to="/search?keyword=apple">검색</Link>
Link에 객체 형태 전달 (pathname, search, state)<Link
to={{
pathname: "/product",
search: "?id=123",
state: { from: "home" },
}}
>
상품 보기
</Link>
pathname: 이동할 주소search: 쿼리스트링state: 임의의 데이터 전달 (브라우저 주소에는 보이지 않음)/search?keyword=apple&page=2
useLocation() + URLSearchParamsimport { useLocation } from "react-router-dom";
const SearchPage = () => {
const location = useLocation();
const query = new URLSearchParams(location.search);
const keyword = query.get("keyword"); // "apple"
const page = query.get("page"); // "2"
return <div>검색어: {keyword}</div>;
};
// 동일한 방식
const query = new URLSearchParams(location.search);
✅ v6에서도
useSearchParams()라는 새로운 hook도 지원합니다.
import { useSearchParams } from "react-router-dom";
const [searchParams, setSearchParams] = useSearchParams();
const keyword = searchParams.get("keyword");
const page = searchParams.get("page");
setSearchParams({ keyword: "banana", page: "1" });
navigate("/detail", { state: { id: 123, from: "home" } });
import { useLocation } from "react-router-dom";
const location = useLocation();
console.log(location.state); // { id: 123, from: "home" }
| 기능 | v5 (react-router-dom@5) | v6 (@6 이상) |
|---|---|---|
| 페이지 이동 | history.push("/path") | navigate("/path") |
| 페이지 덮어쓰기 이동 | history.replace("/path") | navigate("/path", { replace: true }) |
| 쿼리 읽기 | new URLSearchParams(location.search) | useSearchParams() 또는 URLSearchParams |
| 쿼리 쓰기 | 직접 문자열 조작 | setSearchParams({ key: val }) |
| state로 값 전달 | history.push(path, { state }) | navigate(path, { state }) |
| state 값 받기 | location.state | 동일 |
searchParams를 활용한 페이지네이션 구현 예시(쿼리스트링으로 ?page=2처럼 처리)
state를 활용한 로그인 후 리디렉션 예시(로그인 후 원래 있던 페이지로 돌아가기)
두 가지를 실전 예제 중심으로 보여드릴게요.
searchParams로 페이지네이션 구현/posts?page=2
import { useSearchParams } from "react-router-dom";
const PostList = () => {
const [searchParams, setSearchParams] = useSearchParams();
const page = parseInt(searchParams.get("page") || "1", 10);
const handleNext = () => {
setSearchParams({ page: String(page + 1) });
};
const handlePrev = () => {
setSearchParams({ page: String(page - 1) });
};
return (
<div>
<h2>{page} 페이지 게시글</h2>
{/* 게시글 리스트 fetch 등 생략 */}
<button onClick={handlePrev} disabled={page <= 1}>이전</button>
<button onClick={handleNext}>다음</button>
</div>
);
};
export default PostList;
| 코드 | 설명 |
|---|---|
useSearchParams() | 쿼리스트링을 상태처럼 다룸 |
searchParams.get("page") | 현재 page 번호 읽기 |
setSearchParams({ page }) | 주소 변경 (URL에 반영됨) |
/protected 같은 보호된 페이지는 로그인 후에만 접근 가능/login으로 이동import { Navigate, useLocation } from "react-router-dom";
const ProtectedRoute = ({ children }: { children: JSX.Element }) => {
const isLoggedIn = false; // 실제로는 context나 recoil 등에서 가져옴
const location = useLocation();
if (!isLoggedIn) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
};
export default ProtectedRoute;
import { useNavigate, useLocation } from "react-router-dom";
const Login = () => {
const navigate = useNavigate();
const location = useLocation();
const from = location.state?.from?.pathname || "/";
const handleLogin = () => {
// 로그인 처리 후
navigate(from, { replace: true });
};
return (
<div>
<h2>로그인 페이지</h2>
<button onClick={handleLogin}>로그인하기</button>
</div>
);
};
export default Login;
| 코드 | 설명 |
|---|---|
state={{ from: location }} | 현재 위치를 state로 login에 전달 |
location.state?.from?.pathname | 로그인 후 다시 돌아올 경로 |
navigate(from, { replace: true }) | 히스토리 덮어쓰기 방식으로 돌아감 |
| 상황 | 추천 방식 |
|---|---|
| 쿼리스트링 기반 검색/페이지네이션 | useSearchParams() |
| 로그인 후 이전 위치로 복귀 | useNavigate() + state |
| 상태를 URL에 보이고 싶지 않다면 | state 사용, 쿼리스트링은 사용하지 않기 |
/movies/${movieId}와"/movies/:movieId"는 비슷해 보여도 완전히 다른 목적으로 사용됩니다.
${movieId} : 페이지 이동이나 링크를 걸 때
:movieId : 라우터에서 경로를 정의할 때
/movies/:movieId → 경로를 정의할 때(Route path 설정):movieId는 "동적으로 변하는 값"을 의미합니다./movies/123, /movies/abc 등 다양한 movieId에 대응 가능// react-router-dom v6
import { Routes, Route } from "react-router-dom";
import MovieDetail from "./MovieDetail";
<Routes>
<Route path="/movies/:movieId" element={<MovieDetail />} />
</Routes>
/movies/${movieId} → 링크를 걸거나 이동할 때template literals)을 통해 실제 경로를 완성// movieId = 123일 때
<Link to={`/movies/${movieId}`}>상세 보기</Link>
// 또는
navigate(`/movies/${movieId}`);
| 용도 | 사용 예 | 설명 |
|---|---|---|
| 라우터에서 경로 정의 | /movies/:movieId | :movieId는 "변수", 어떤 id에도 대응 가능 |
| 링크/이동 시 경로 작성 | /movies/${movieId} | 실제 값이 들어간 URL로 이동함 |
<Route path="/movies/:movieId" element={<MovieDetail />} />
<Link to={`/movies/${movie.id}`}>상세 보기</Link>
movieId 꺼내기:import { useParams } from "react-router-dom";
const MovieDetail = () => {
const { movieId } = useParams();
return <div>영화 ID: {movieId}</div>;
};