์์ ํ ์คํธ๋ง ์์ผ๋ฉด ๋ฐ๋ฐํ๋๊น ์ค์ ์ํ ์ ๋ณด๋ฅผ ๋ฃ์ด๋ด ์๋ค!
App.js:
<Route path="/detail" element={ <Detail shoes={shoes}/> }/>
Detail.js:
<div className="container">
<div className="row">
<div className="col-md-6">
<img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
</div>
<div className="col-md-6 mt-4">
<h4 className="pt-5">{props.shoes[0].title}</h4>
<p>{props.shoes[0].content}</p>
<p>{props.shoes[0].price}์</p>
<button className="btn btn-danger">์ฃผ๋ฌธํ๊ธฐ</button>
</div>
</div>
</div>
props ์ฌ์ฉ ์ด์ :
<Route path="/detail/0" element={ <Detail shoes={shoes}/> }/>
<Route path="/detail/1" element={ <Detail shoes={shoes}/> }/>
<Route path="/detail/2" element={ <Detail shoes={shoes}/> }/>
๋ฌธ์ ์ : ์ํ์ด 100๋ง ๊ฐ๋ผ๋ฉด Route๋ 100๋ง ๊ฐ ๋ง๋ค์ด์ผ ํจ ๐ฑ
<Route path="/detail/:id" element={ <Detail shoes={shoes}/> }/>
/:id - "์๋ฌด ๋ฌธ์"๋ฅผ ์๋ฏธ/detail/์๋ฌด๊ฑฐ๋ ์
๋ ฅ ์ <Detail> ์ปดํฌ๋ํธ ํ์/)๋ ๋จ์ด ๊ฐ ๋์ด์ฐ๊ธฐ์ฉ์ผ๋ก ์ฌ์ฉ์ด์ ๋ค์ URL๋ค์ด ๋ชจ๋ ์๋ํฉ๋๋ค:
/detail/0/detail/1 /detail/2ํ์ด์ง๋ง๋ค ๋ค๋ฅธ ์ํ์ ๋ณด์ฌ์ฃผ๋ ค๋ฉด ํ์ฌ URL์ ํ๋ผ๋ฏธํฐ ๊ฐ์ ๊ฐ์ ธ์์ผ ํฉ๋๋ค.
import { useParams } from 'react-router-dom'
function Detail(props){
let {id} = useParams();
console.log(id) // URL์ :id ๋ถ๋ถ ๊ฐ ์ถ๋ ฅ
return (
<div className="container">
<div className="row">
<div className="col-md-6">
<img src="https://codingapple1.github.io/shop/shoes1.jpg" width="100%" />
</div>
<div className="col-md-6 mt-4">
<h4 className="pt-5">{props.shoes[id].title}</h4>
<p>{props.shoes[id].content}</p>
<p>{props.shoes[id].price}์</p>
<button className="btn btn-danger">์ฃผ๋ฌธํ๊ธฐ</button>
</div>
</div>
</div>
)
}
/detail/1 ์ ์ โ id ๋ณ์์ "1" ์ ์ฅ/detail/2 ์ ์ โ id ๋ณ์์ "2" ์ ์ฅprops.shoes[id].title๋ก ํด๋น ์ํ๋ช
ํ์// path ์ค์
<Route path="/detail/:category/:id" element={<Detail />} />
// useParams ์ฌ์ฉ
let {category, id} = useParams();
// /detail/shoes/1 โ category="shoes", id="1"
์ํ์ ๊ฐ๋๋ค์์ผ๋ก ์ ๋ ฌํ๋ ๋ฒํผ์ ๋ง๋ค์๋ค๊ณ ๊ฐ์ :
White and Black์ด 0๋ฒ ์ํGrey Yordan์ด 0๋ฒ ์ํ์ด ๋จ/detail/0 ์ ์ ์ ๋ค๋ฅธ ์ํ์ด ๋ณด์!๋ฐฐ์ด ์ธ๋ฑ์ค ๋์ ๊ณ ์ ํ ์๋ณ์(id)๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค!
URL ํ๋ผ๋ฏธํฐ (Path Parameter):
/detail/123 โ 123์ URL ํ๋ผ๋ฏธํฐ
/user/john/posts/5 โ john๊ณผ 5๋ URL ํ๋ผ๋ฏธํฐ
์ฟผ๋ฆฌ ์คํธ๋ง (Query String):
/products?category=shoes&size=large
/search?q=react&page=2
1. useParams - URL ํ๋ผ๋ฏธํฐ์ฉ
// URL: /product/123
const { id } = useParams();
console.log(id); // "123"
2. useSearchParams - ์ฟผ๋ฆฌ ์คํธ๋ง์ฉ
// URL: /products?category=shoes&page=2
const [searchParams] = useSearchParams();
console.log(searchParams.get('category')); // "shoes"
console.log(searchParams.get('page')); // "2"
1. ID ๊ธฐ๋ฐ ๊ฒ์ ๋ฐฉ์
function Detail(props) {
const { id } = useParams();
// ์ธ๋ฑ์ค ๋์ ID๋ก ์ฐพ๊ธฐ
const product = props.shoes.find(shoe => shoe.id === parseInt(id));
if (!product) {
return <div>์ํ์ ์ฐพ์ ์ ์์ต๋๋ค.</div>;
}
return (
<div>
<h4>{product.title}</h4>
<p>{product.content}</p>
<p>{product.price}์</p>
</div>
);
}
2. ์๋ฌ ์ฒ๋ฆฌ ๊ฐํ
function Detail(props) {
const { id } = useParams();
const navigate = useNavigate();
useEffect(() => {
// ์ ํจํ์ง ์์ ID๋ฉด 404๋ก ๋ฆฌ๋ค์ด๋ ํธ
const product = props.shoes.find(shoe => shoe.id === parseInt(id));
if (!product) {
navigate('/404', { replace: true });
}
}, [id, props.shoes, navigate]);
// ... ์ปดํฌ๋ํธ ๋ ๋๋ง
}
1. ์ต์ ๋ ํ๋ผ๋ฏธํฐ
// ์นดํ
๊ณ ๋ฆฌ๊ฐ ์์ ์๋ ์์ ์๋
<Route path="/products/:category?" element={<Products />} />
function Products() {
const { category } = useParams();
// category๊ฐ undefined์ผ ์ ์์
return category ? (
<div>{category} ์นดํ
๊ณ ๋ฆฌ ์ํ๋ค</div>
) : (
<div>์ ์ฒด ์ํ</div>
);
}
2. ์์ผ๋์นด๋์ ํ๋ผ๋ฏธํฐ ์กฐํฉ
<Route path="/files/*" element={<FileViewer />} />
function FileViewer() {
const location = useLocation();
const filePath = location.pathname.replace('/files/', '');
// /files/docs/readme.txt โ filePath = "docs/readme.txt"
}
1. ๋ฉ๋ชจ์ด์ ์ด์ ํ์ฉ
function Detail(props) {
const { id } = useParams();
const product = useMemo(() => {
return props.shoes.find(shoe => shoe.id === parseInt(id));
}, [props.shoes, id]);
return product ? <ProductView product={product} /> : <NotFound />;
}
2. ๋ฐ์ดํฐ ์ฌ์ ๋ก๋ฉ
// ์ํ ๋ชฉ๋ก์์ ์์ธํ์ด์ง๋ก ์ด๋ํ๋ ๋งํฌ
function ProductCard({ product }) {
const handleMouseEnter = () => {
// ๋ง์ฐ์ค ํธ๋ฒ ์ ์์ธ ๋ฐ์ดํฐ ๋ฏธ๋ฆฌ ๋ก๋
preloadProductDetails(product.id);
};
return (
<Link
to={`/detail/${product.id}`}
onMouseEnter={handleMouseEnter}
>
{product.title}
</Link>
);
}
1. ์ง๊ด์ ์ธ URL ๊ตฌ์กฐ
โ
์ข์ ์:
/products/123
/categories/electronics/products/456
/users/john/orders/789
โ ๋์ ์:
/page?type=product&id=123
/electronics123
/johnorders789
2. RESTful URL ํจํด
// ์ํ ๊ด๋ จ
/products // ์ํ ๋ชฉ๋ก
/products/123 // ์ํ ์์ธ
/products/new // ์ํ ์ถ๊ฐ
/products/123/edit // ์ํ ์์
// ์ฌ์ฉ์ ๊ด๋ จ
/users/456 // ์ฌ์ฉ์ ํ๋กํ
/users/456/orders // ์ฌ์ฉ์ ์ฃผ๋ฌธ ๋ชฉ๋ก
/users/456/orders/789 // ํน์ ์ฃผ๋ฌธ ์์ธ