이제 상세 페이지에 데이터를 뿌려주기위해 두가지 URL이 필요하다
INFODATA
https://api.coinpaprika.com/v1/coins/${coinId}
PRICEDATA
https://api.coinpaprika.com/v1/tickers/${coinId}
우리 전에 페이지 로딩 처음에만 정보를 불러오려면 뭘해야 된다고 했지?
useEffect다
useEffect(() => {
(async () => {
const response = await fetch("https://api.coinpaprika.com/v1/coins");
const json = await response.json();
setCoins(json.slice(0, 100));
setLoading(false);
})();
}, []);
원래 이렇게 2줄로 써야하지만깔끔하게 한줄로도 쓸 수 있다.
useEffect(() => {
(async () => {
const response = await (
await fetch(`https://api.coinpaprika.com/v1/coins/${coinId}`)
).json();
})();
}, []);
이렇게 말이다.
infodata와 pricedata가 모두 필요하니
두줄을 써주자.
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);
setLoading(false);
})();
}, []);
근데 저기에서 infoData와 pricedata는 빈 object로 typescript가 판단하여 오류가 난다.
그러기 위해선 먼저 interface를 만들어줘야 하는데
pricedata와 infodata의 데이타값을 console.log로 받아와서
콘솔창에서 받아온 값의 오른쪽을 클릭하여 store object as global variable 을 눌러준다
그러면 temp1라고 임시로 저장이 되는데 우리는 여기에서 값을 긁어올거다.
Object.keys(temp1).join()로 항목들을 긁어오고
Object.values(temp1).map(v => typeof v).join 으로 data 타입을 받아온다.
interface IInfoData {
id: string;
name: string;
symbol: string;
rank: number;
is_new: boolean;
is_active: boolean;
type: string;
logo: string;
tags: object;
team: object;
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;
links: object;
links_extended: object;
whitepaper: object;
first_data_at: string;
last_data_at: string;
}
이렇게 정리된다. 근데 이중에 tags랑 team항목이 있는데 이건 object가 아니라 []
다.
그래서 interface 를 하나 만들어주고
interface Itag {
coin_counter: number;
ico_counter: number;
id: string;
name: string;
}
interface IInfoData {
.
.
.
tags: Itag[];
.
.
이렇게 처리해준다. 근데 저렇게 object 들어간건 우리가 만들 프로젝트에 필요없으니 빼도 된다고한다....
떼잉.
import { useEffect, useState } from "react";
import { useLocation, useParams } from "react-router";
import styled from "styled-components";
const Title = styled.h1`
font-size: 48px;
color: ${(props) => props.theme.accentColor};
`;
const Loader = styled.span`
text-align: center;
display: block;
`;
const Container = styled.div`
padding: 0px 20px;
max-width: 480px;
margin: 0 auto;
`;
const Header = styled.header`
height: 15vh;
display: flex;
justify-content: center;
align-items: center;
`;
interface RouteParams {
coinId: string;
}
interface RouteState {
name: string;
}
interface Itag {
coin_counter: number;
ico_counter: number;
id: string;
name: string;
}
interface InfoData {
id: string;
name: string;
symbol: string;
rank: number;
is_new: boolean;
is_active: boolean;
type: string;
logo: 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;
links: object;
first_data_at: string;
last_data_at: string;
}
interface PriceData {
id: string;
name: string;
symbol: string;
rank: number;
circulating_supply: number;
total_supply: number;
max_supply: number;
beta_value: number;
first_data_at: string;
last_updated: string;
quotes: {
USD: {
ath_date: number;
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;
};
};
}
function Coin() {
const [loading, setLoading] = useState(true);
const { coinId } = useParams<RouteParams>();
const { state } = useLocation<RouteState>();
const [info, setinfo] = useState<InfoData>();
const [priceInfo, setPriceInfo] = useState<PriceData>();
useEffect(() => {
(async () => {
const infoData = await (
await fetch(`https://api.coinpaprika.com/v1/coins/${coinId}`)
).json();
console.log(infoData);
const priceData = await (
await fetch(`https://api.coinpaprika.com/v1/tickers/${coinId}`)
).json();
console.log(priceData);
setinfo(infoData);
setPriceInfo(priceData);
// setLoading(false);
})();
}, []);
return (
<Container>
<Header>
<Title>{state?.name || "Loading..."}</Title>
</Header>
{loading ? <Loader>Loading...</Loader> : null}
</Container>
);
}
export default Coin;
여기까지가 Coin Data와 Data Type이다.