5.8강
const { url, path } = useRouteMatch();
<Link to={`${url}/price`}>PRICE</Link>
<Link to={`${url}/chart`}>CHART</Link>
<Switch>
<Route path={`${path}/price`}>
<Price />
</Route>
<Route path={`${path}/chart`}>
<Chart />
</Route>
</Switch>
<Link to={`/${coinId}/price`}>PRICE</Link>
<Link to={`/${coinId}/chart`}>CHART</Link>
<Switch>
<Route path={`${coinId}/price`}>
<Price />
</Route>
<Route path={`${coinId}/chart`}>
<Chart />
</Route>
</Switch>
<Route>의 path와 <Link>의 to가 서로 다른 목적과 동작 방식을 가지고 있기 때문에, 슬래시(/)를 쓰는 규칙도 다름
<Route path> 에는 패턴을 정의한다path는 “이 URL 패턴을 만나면 이 컴포넌트를 렌더링”하겠다는 매칭 규칙이에요. /를 빼고 상대 경로로 쓸 수 있습니다. // 상위에 이미 path="/:coinId" 가 있는 상태
<Route path="/:coinId">
{/* ⇒ 실제 매칭은 "/:coinId/price" */}
<Route path="price" component={Price} />
{/* ⇒ 실제 매칭은 "/:coinId/chart" */}
<Route path="chart" component={Chart} />
</Route>path="price"처럼 쓰면 내부적으로 /:coinId/price로 확장돼요. price 앞에 /를 붙이면 “루트(/)부터 시작하는 절대경로”가 되어,<Link to> 에는 실제 URL을 지정한다to는 “사용자가 클릭했을 때 이동할 정확한 경로”를 문자열로 받습니다. /로 시작하면 절대경로,/btc-bitcoin일 때…to="price" → /btc-bitcoin/price 로 이동 to="btc-bitcoin/price" → /btc-bitcoin/btc-bitcoin/price (원치 않는 중첩) to="/btc-bitcoin/price" → /btc-bitcoin/price (안정적인 절대경로)// 올바른 예: 절대경로로 딱 이동
<Link to={`/${coinId}/price`}>PRICE</Link>
<Link to={`/${coinId}/chart`}>CHART</Link>
import { useRouteMatch, Link, Route, Switch } from "react-router-dom";
function Coin() {
const { url, path } = useRouteMatch();
// url = 현재 실제 URL 예: "/btc-bitcoin"
// path = 현재 매칭 패턴 예: "/:coinId"
return (
<>
<nav>
{/* url을 쓰면 항상 절대경로 */}
<Link to={`${url}/price`}>PRICE</Link>
<Link to={`${url}/chart`}>CHART</Link>
</nav>
<Switch>
{/* path를 쓰면 항상 패턴 매칭 */}
<Route path={`${path}/price`}>
<Price />
</Route>
<Route path={`${path}/chart`}>
<Chart />
</Route>
</Switch>
</>
);
}
url: 절대경로로 Link path: 패턴(동적 세그먼트)으로 Route 이렇게 하면
path 에는 플레이스홀더(패턴) to 에는 실제 URL(절대경로)/btc-bitcoin/price가 중첩 없이 딱 맞아떨어집니다.<Route path> 에는 패턴(pattern) 을 정의한다// (1) JSX 속성에 고정된 문자열만 쓰면, 문자열 리터럴로 인식됩니다.
<Route path="/:coinId/chart">
<Chart />
</Route>
/:coinId/chart : 은 React Router의 문법으로, 이 자리에 “동적 세그먼트”가 온다고 알려주는 표시예요. /:coinId/chart는 /btc-bitcoin/chart, /ethereum/chart 등 어떤 코인 아이디에도 매칭됩니다. ${...} 같은 JS 변수 삽입 없이 그냥 ":coinId" 형태를 쓰는 거예요. <Route>의 path 속성은 “이 URL 패턴이 들어올 때 이 컴포넌트를 렌더링”할지를 정의하는 용도입니다.<Link to> 에는 실제 값이 들어간 JS 표현식(expression) 을 써야 한다// (2) coinId 변수에 담긴 실제 값을 넣기 위해서는
// JSX에서 {…} 안에 JS 표현식을 써야 합니다.
<Link to={`/${coinId}/chart`}>CHART</Link>
${coinId} `…`) 안에서 ${coinId}로 변수 값을 문자열에 삽입하는 템플릿 리터럴 문법이에요. "btc-bitcoin" 이면, `/${coinId}/chart` → "/btc-bitcoin/chart" { … } 로 감싸야 합니다. <Link to="/some/static/path"> 처럼 고정 문자열만 쓸 땐 {} 없이 쓸 수 있지만, {``} 안에 써야 동작합니다.| 역할 | 경로 예시 | 사용법 |
|---|---|---|
| Route path | /:coinId/chart | <Route path="/:coinId/chart">…</Route>— 동적 세그먼트 패턴, 변수 삽입 아님 |
| Link to | /${coinId}/chart | <Link to={/${coinId}/chart}>…</Link>— JS 변수 삽입한 실제 URL |
:coinId → 라우터가 URL에서 그 자리에 오는 값을 파싱(예: /bitcoin/chart) ${coinId} → 현재 컴포넌트 내부의 JS 변수 값을 넣어서 실제 URL을 생성 useParams()
import { useParams } from "react-router-dom";
function Chart() {
const { coinId } = useParams();
// coinId === "btc-bitcoin"
return <div>{coinId} 의 차트</div>;
}
Link
<Link to={`/${coinId}/price`}>PRICE</Link>
이제
path="/:coinId/chart" 에서는 패턴을, to={/${coinId}/chart} 에서는 실제 값이 들어간 URL을 지정한다는 차이를| 속성 | 용도 | 예시 |
|---|---|---|
<Route path> | “어떤 URL 패턴”을 등록 | path="/:coinId/price" → /btc-bitcoin/price처럼 매칭 |
<Link to> | “어디로 이동할 것인지”를 지정 | to="/btc-bitcoin/price" → 실제로 /btc-bitcoin/price로 이동 |
:coinId 처럼 플레이스홀더(동적 세그먼트)를 씁니다. /btc-bitcoin/price 같은 절대경로를 만듭니다.// 1) Route 정의: 동적 세그먼트(:coinId) 사용
<Switch>
<Route path="/:coinId/price">
<Price />
</Route>
<Route path="/:coinId/chart">
<Chart />
</Route>
</Switch>
// 2) Link 클릭: 실제 coinId 값을 채워서 절대경로 생성
// coinId 가 "btc-bitcoin" 이라고 가정
<Link to={`/${coinId}/price`}>PRICE</Link>
// → 실제로 to="/btc-bitcoin/price" 로 이동합니다.
path="/:coinId/price" /btc-bitcoin/price일 때 <Price>가 보인다!to={/${coinId}/price} coinId 변수에 담긴 "btc-bitcoin"을 문자열에 그대로 넣어/btc-bitcoin/price로 이동시킨다!플레이스홀더 vs. 실제 값
path = 패턴 (/:coinId/price) to = 실제 URL (/btc-bitcoin/price)절대경로의 안정성
to="price" 같은 상대경로는/… (절대경로) 로 쓰는 게 깔끔합니다.| 구분 | 잘못된 코드 (헷갈림) | 올바른 코드 (추천) |
|---|---|---|
| Route(path) | <Route path={/${coinId}/price}>(변수 치환 X) | <Route path="/:coinId/price"> |
| Link(to) | <Link to={${coinId}/price}>(상대경로) | <Link to={/${coinId}/price}> |
:coinId /${coinId} 5.9강
CoinList.tsx
const [coins, setCoins] = useState<ICoins[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
(async() => {
const response = await fetch("https://api.coinpaprika.com/v1/coins");
const json = await response.json();
setCoins(json.slice(0, 20));
setLoading(false);
})();
}, []);
api.ts
export function fetchCoins(){
return fetch("url").then((response) => response.json());
}
CoinList.tsx
const { isLoading, data } = useQuery("allCoinsData", fetchCoins);
//{...중략...}
{data.slice(0, 20).map((coin.....중략.....