이제 Coin.tsx 페이지에 본격적으로 데이터를 가져올 시간.
코인의 정보를 알려주는 url, 해당 코인의 가격이 상세하게 나와있는 url 두 가지를 사용해서 구현하는 것이 목표!
https://api.coinpaprika.com/v1/coins/btc-bitcoin
https://api.coinpaprika.com/v1/tickers/btc-bitcoin
function Coin() {
const [loading, setLoading] = useState(true);
const { coinId } = useParams<RouteParams>(); <<<--- coinId!!
const { state } = useLocation<RouteState>();
const [info, setInfo] = useState({});
const [priceInfo, setPriceInfo] = useState({});
useEffect(() => {
(async () => {
const infoData = await (
await fetch(`https://api.coinpaprika.com/v1/coins/${coinId}`)
).json();
const priceData = await (
await fetch(`https://api.coinpaprika.com/v1/tickers/${coinId}`)
).json();
setInfo(infoData);
setPriceInfo(priceData);
})();
}, []);
return (
setInfo
, setPriceInfo
안에 데이터를 넣어줬다.info
, priceInfo
둘은 타입스크립트가 보자면 '엥 넌 비어있는 obj 아님?;;' 하고 에러를 띄우기 때문.interface
를 사용해 타입스크립트에게 어떤 정보들이 있고 어떤 데이터 타입들인지 알려주어야 한다!interface InfoData {
id: string;
name: string;
symbol: string;
rank: number;
is_new: boolean;
is_active: boolean;
type: string;
description: string;
message: string;
open_source: boolean;
started_at: string;
development_status: string;
hardware_wallet: boolean;
proof_type: string;
org_structure: string;
hash_algorithm: string;
first_data_at: string;
last_data_at: string;
}
object.keys(temp1).join()
코드를 실행하면 obj 안에 있던 데이터들이 string 한줄로 출력됨! 복붙 ㄱobject.values(temp1).map( v => typeof v).join()
tags : ITag[];
이런식으로 직접 설명해주어야한다.const [info, setInfo] = useState<InfoData>();
interface PriceData
도 동일한 방법으로 하면 되는데,quotes
항목이 object 이므로 설명해준다.interface PriceData {
.
.
.
last_updated: string;
quotes: {
USD: {
ath_date: string;
ath_price: number;
market_cap: number;
market_cap_change_24h: number;
percent_change_1h: number;
percent_change_1y: number;
percent_change_6h: number;
percent_change_7d: number;
percent_change_12h: number;
percent_change_15m: number;
percent_change_24h: number;
percent_change_30d: number;
percent_change_30m: number;
percent_from_price_ath: number;
price: number;
volume_24h: number;
volume_24h_change_24h: number;
};
};
}
데이터를 다 받아왔으니, screen 에 뿌려줄 차례
총 세개의 컴포넌트를 만들어 화면을 만들었다.
하단에는 가격 데이터로 chart 를 보여주고, price 에서는 가격변동 데이터를 보여줄 예정
chart, price 탭을 Nested Routes 통해 '/btc-bitcoin/chart' , '/btc-bitcoin/price' 와 같이 만들 것
우선 2개의 route 를 만들어야 한다.
'Price.tsx' / 'Chart.tsx' 생성!
이제 'Coin.tsx' 페이지에 route 를 추가해주어야하는데..
강의에서는 react router-dom 5.3 버전을 사용하나, 나는 6.2버전을 사용중이여서 적용되지 않았다.
<Outlet>
을 사용하지 않는 방법으로 채택했다.- Router.tsx
function Router() {
return (
<BrowserRouter>
<Routes>
{/* nested route 으로 자식 route 는 상대경로로 작성한다. */}
<Route path="/" element={<Coins />}></Route>
<Route path="/:coinId" element={<Coin />}></Route>
<Route path="/:coinId/*" element={<Coin />} /> <<<----
</Routes>
</BrowserRouter>
);
}
- Coin.tsx
<Routes>
<Route path="chart" element={<Chart />} />
<Route path="price" element={<Price />} />
</Routes>
- router.tsx
<Route path="/:coinId" element={<Coin />} >
<Route path="chart" element={<Chart />} />
<Route path="price" element={<Price />} />
- Coin.tsx
import Outlet from "react-router-dom"
...
넣고자하는 곳에 <Outlet /> 작성
Outlet (중첩 라우트 사용하기)
자식 라우트의 엘리먼트가 있는 경우 렌더링한다.
Outlet은 부모 경로 요소에서 자식 경로 요소를 렌더링하는 데 사용해야 합니다.
이를 통해 하위 경로가 렌더링될 때 중첩된 UI를 표시할 수 있습니다. 부모 라우트가 정확히 일치하면 자식 인덱스 라우트를 렌더링하거나 인덱스 라우트가 없으면 아무것도 렌더링하지 않습니다.
Outlet
은 이해가 더 완전히 되면 사용하기 위해 우선 첫번째 방법을 사용했다.- Coin.tsx
<Tabs>
<Tab>
<Link to={`/${coinId}/chart`}>Chart</Link>
</Tab>
<Tab>
<Link to={`/${coinId}/price`}>Price</Link>
</Tab>
</Tabs>
<Routes>
<Route path="chart" element={<Chart />} />
<Route path="price" element={<Price />} />
</Routes>
useMatch()
hook 을 사용해줬다.isExact : true
를 반환, 아니라면 null
을 반환. const priceMatch = useMatch("/:coinId/price");
const chartMatch = useMatch("/:coinId/chart");
<Tab>
컴포넌트에 추가해주면 된다 :)<Tab>
컴포넌트에 isActive
라고 불리는 prop 을 추가했다.const Tab = styled.span<{ isActive: boolean }>`
isActive / 속성값 : Boolean
창이 활성 상태이면 true이고, 그렇지 않으면 false. 기본값 false
- Coin.tsx
<Tabs>
<Tab isActive={chartMatch !== null}> <<<----
{/* chartMatch 에서 chart(url)이 맞지 않으면 null나옴 */}
<Link to={`/${coinId}/chart`}>Chart</Link>
</Tab>
<Tab isActive={priceMatch !== null}> <<<----
<Link to={`/${coinId}/price`}>Price</Link>
</Tab>
</Tabs>