[SeSACx코딩온] useParams, useSearchParams, useNavigate
useParams
, useSearchParams
, useNavigate
1. React Router 훅이란?
React Router에서 제공하는 훅(Hook)은 페이지 간 이동과 URL 관련 정보를 쉽게 처리할 수 있도록 합니다. 그 중에서도 useParams
, useSearchParams
, useNavigate
는 URL 경로의 파라미터, 쿼리 파라미터, 페이지 이동에 있어 제어하는데 필수적인 훅입니다.
2. React Router 훅
1) useParams
로 URL 경로 파라미터 추출
useParams
는 URL 경로에서 동적 경로 파라미터를 추출하는 훅입니다. 예를 들어, /products/:productId
와 같은 경로에서 :productId
에 해당하는 값을 가져와 사용할 수 있습니다.
components/ProductList.js
import React from "react";
import ProductItem from "./ProductItem";
export const productInfos = [
{
userId: 1,
id: 1,
title: "첫 번째 상품",
body: "첫 번째 상품 설명입니다.",
},
{
userId: 1,
id: 2,
title: "두 번째 상품",
body: "두 번째 상품 설명입니다.",
},
];
export default function ProductList() {
return (
<div>
{productInfos.map((product) => (
<ProductItem key={product.id} product={product} />
))}
</div>
);
}
pages/ProductDetailPage.js
import React from "react";
import { useParams } from "react-router-dom";
import { productInfos } from "../components/ProductList";
export default function ProductDetailPage() {
const { productId } = useParams(); // URL 경로에서 productId를 추출
console.log("productId >>> ", productId); // '3' = 'id'
const targetProduct = productInfos[Number(productId) - 1]; // productId로 배열에서 해당 상품 조회
return (
<div>
<h1>ProductDetailPage</h1>
<ul>
<li>상품번호: {targetProduct.id}</li>
<li>상품명: {targetProduct.title}</li>
<li>판매자: {targetProduct.userId}</li>
<li>상세설명: {targetProduct.body}</li>
</ul>
</div>
);
}
productInfos
는 상품 정보를 담은 배열입니다. 각 상품은id
,title
,userId
,body
의 속성을 가진 객체로 정의되어 있으며, 배열 안에 여러 상품이 있습니다.- 배열 인덱스와 파라미터 값 차이: 파라미터로 전달된
productId
는 1부터 시작하지만, 배열의 인덱스는 0부터 시작하므로,-1
을 적용하여 배열의 요소에 접근할 수 있습니다.
2) useSearchParams
로 쿼리 파라미터 관리하기
useSearchParams
는 URL의 쿼리 파라미터를 읽고, 이를 동적으로 수정할 수 있는 훅입니다. 쿼리 파라미터는 URL 뒤에 ?key=value
형태로 붙으며, 검색 조건, 필터링 등에 주로 사용됩니다.
/pages/MainPage.js
import React from "react";
import { useSearchParams } from "react-router-dom";
export default function MainPage() {
const [searchParams, setSearchParams] = useSearchParams(); // 현재 쿼리 파라미터를 가져옴
const currentMode = searchParams.get("mode") || ""; // 쿼리에서 'mode' 값 추출
const toggleMode = () => {
if (currentMode === "Dark") {
searchParams.delete("mode"); // Dark 모드일 때 쿼리 파라미터 삭제
setSearchParams(searchParams);
} else {
setSearchParams({ mode: "Dark" }); // Dark 모드로 설정
}
};
return (
<div className={`Main ${searchParams.get("mode") || ""}`}>
<h1>MainPage</h1>
<button onClick={toggleMode}>
{currentMode === "Dark" ? "Default Mode" : "Dark Mode"}
</button>
</div>
);
}
(1) 쿼리 파라미터와 ||
연산자
- 쿼리 파라미터는 URL의 일부로, 페이지 상태나 필터 조건을 유지하기 위해 사용됩니다. 예를 들어,
?mode=Dark
라는 쿼리 파라미터는 페이지가 다크 모드인지 여부를 나타낼 수 있습니다. -
setSearchParams
를 이용해 쿼리 파라미터를 동적으로 변경하거나 삭제할 수 있습니다. 위 코드에서는 버튼을 클릭하면 쿼리 파라미터가mode=Dark
로 설정되거나, 삭제되어 기본 모드로 전환됩니다. ||
연산자 사용:searchParams.get('mode')
가null
일 때(falsy),||
연산자가 작동하여 빈 문자열''
을 반환합니다. 이를 통해null
이나undefined
대신 기본값을 지정할 수 있습니다.- 예를 들어, 쿼리 파라미터가 없을 때,
currentMode
는 빈 문자열이 됩니다.const currentMode = searchParams.get("mode") || ""; // 없으면 '' 반환
(2) 다크 모드 설정 방식
이 부분에서는 CSS 클래스를 동적으로 적용하여 다크 모드와 기본 모드를 변경하는 방식이 두 가지로 나뉩니다.
join
을 사용하는 방법
- 배열에 클래스 이름들을 넣고,
join
메서드를 사용하여 공백을 기준으로 합칩니다. 이는 클래스 이름을 다루기 쉽게 만들어줍니다.
<div className={['Main', searchParams.get('mode')].join(' ')}>
<!-- [Main, Dark].join(' ') => Main Dark -->
백틱(
)을 사용하는 방법
- 템플릿 리터럴을 이용하여 백틱으로 문자열을 생성하고, 조건에 따라 클래스 이름을 삽입합니다.
<div className={`Main ${searchParams.get('mode') || ''}`}>
(3) CSS로 다크 모드 구현
.Main {
background-color: #ddd;
}
.Main.Dark {
background-color: #333;
color: #fff;
}
Main
클래스는 기본 모드를 나타내고,Main.Dark
는 다크 모드에서 사용될 CSS입니다.- 다크 모드일 때: 쿼리 파라미터가
mode=Dark
이면,Main Dark
라는 클래스가 적용됩니다. - 기본 모드일 때:
mode
쿼리 파라미터가 없으면 기본적인Main
클래스만 적용됩니다.
3) useNavigate
로 페이지 이동 제어
/pages/ProductDetailPage.js
import React from "react";
import { useNavigate, useParams } from "react-router-dom";
import { productInfos } from "../components/ProductList";
export default function ProductDetailPage() {
const { productId } = useParams();
const navigate = useNavigate(); // 페이지 이동을 위한 훅
const targetProduct = productInfos[Number(productId) - 1];
return (
<div>
<h1>ProductDetailPage</h1>
<button onClick={() => navigate(-1)}>뒤로가기</button> {/* -1: 이전 페이지로 이동 */}
<button onClick={() => navigate("/")}>홈으로 이동하기</button>{" "}
{/* 홈으로 이동 */}
<ul>
<li>상품번호: {targetProduct.id}</li>
<li>상품명: {targetProduct.title}</li>
<li>판매자: {targetProduct.userId}</li>
<li>상세설명: {targetProduct.body}</li>
</ul>
</div>
);
}
navigate(-n)
: -1을 사용하면 이전 페이지로 이동합니다. 이는 브라우저의 뒤로가기 버튼과 동일한 기능을 합니다.navigate(n)
: 1을 사용하면 다음 페이지로 이동합니다. 이는 브라우저의 앞으로 가기 버튼과 동일한 기능을 합니다.navigate('/')
: 홈 페이지로 직접 이동할 수 있습니다.