CRYPTO TRACKER 4.5~4.6 _ Coin Data & CoinTypes

Eugenius1st·2022년 3월 12일
0

ReactJS_MasterClass

목록 보기
22/48
post-custom-banner

Coin Data

비트코인Detail 화면에 뿌려줄 데이터를 가져올 것이다.


코인의 정보와 가격을 가져올 것이다
현재 parameter에 존재하는 coinId를 이용할 것이다.
useEffect를 이용해 코드가 한번만 실행되게 할 것이다.API를 가져오고 이후 React Query로 더 간단하게 만들어 볼 것이다. 일단 만들자



뒷부분만 파라미터로 coinId 사용하도록바꿔준다.

좀 더 짧게 바꾸는 방법
await를 한줄에 쓸 수 있다.
await로 감싸주면 된다.


이것을 캡슐화라고 한다 ~!!

변수 두개를 쓸 바에 한번에 시간을 절약해서 작성할 수 있는 방법이다.
이제 받아올 priceData 변수를 만들자


두가지 정보를 받았다.
필요한 데이터가준비되었다. 이제 state 안에 붙여주자.

객체로 일단 {} 설정
그 안에 setInfo, setProceInfo를 설정해준다.

그 전에 typescript에 데이터 설명 위해 배울 것이 있다

Coin Types

데이터를 이용하기 위해


변수에 따로 저장해 놓으면 좋다


id : 로 시작해서 정의하고 싶지,
hardware_wallet: 으로 정의하고 싶지 않기 때문이다.

그 전에 interface두개를 만들어둔다.

이후 join으로 string이 나오는지 확인하여

interface에 복붙해주어 콤마 바로 앞에서 삭제 후 엔터를 누르면

모든 키들이 정렬되고 ctrl + shift + l 을 눌러 커서를 받아서 : 를 입력해준다.

이번에는 keys 대신 values를 받아올 것

value 의 type 을 map으로 하나씩 받아와 보자..

이제 key들과 매칭시키자.
모든 쉼표들을 클릭하고 엔터..
ctrl + shift + l 하고 커서로 전부 복붙한다.

여기서 주의할 점은 tags와 team 같은 경우에는 type 이 array인 것이다.
그래서 내부에 Itag라는 interface 를 하나 더 만들어줘야 한다.

그리고
ITag를 추가한다.
그 외의 object라고 써있는 친구들은 필요 없으니 지워주자..InfoData에서..

그리고 나서 typeScript의 type 들을 매칭시키기 위해

InfoData를 입력한다.


이제 info. 하면 자동완성으로 가져올 수 있는 것들을 확인할 수 있다.

PriceData도 마찬가지로 해주자.


첫번째 string 부터 복사하고 붙여넣는다..


여기서 중요한 친구는 quotes 밖에 없다.

이 친구는 내부에 값이 많으므로 따로 정의해줘야 한다.


number로 바꿔주는 것이다.

그리고
이렇게 붙여넣기 한 후 기본 값에 중괄호는 필요 없으니 제거해준다.

이제 qutoes.USD 하면 많은 것들을 확인할 수 있다.

Coins

import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { useEffect, useState } from 'react';

const Container = styled.div`
  padding: 0px 20px;
  max-width: 480px;
  margin: 0 auto;
`;

const Header = styled.header`
  height: 20vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;

const CoinsList = styled.ul``;

const Coin = styled.li`
  background-color: white;
  color: ${(props) => props.theme.bgColor};
  margin-bottom: 10px;
  padding: 20px;
  border-radius: 15px;

  a {
    padding: 5px; // 좀 더 넓은 범위에서 transition 효과 적용 가능
    transition: color 0.2s ease-in;
  }

  &:hover {
    a {
      color: ${(props) => props.theme.accentColor};
    }
    // 아래에서는 a가 아닌 Link라는 이름으로 사용했지만
    // css에서는 anchor 를 선택해야 했다. 이건 모든 react router link들이
    // 결국에는 anchor로 바뀔거기도 하고,
    // react router dom이 우리 대신 설정을 도와줄 특별한 event listener들이 있기도 하다
  }
`;

const Title = styled.h1`
  font-size: 48px;
  color: ${(props) => props.theme.accentColor};
`;

const Loader = styled.span`
  text-align: center;
  display: block;
`;

const Img = styled.img`
  width: 25px;
  height: 25px;
  margin-right: 10px;
`;

interface CoinInterface {
  id: string;
  name: string;
  symbol: string;
  rank: number;
  is_new: boolean;
  is_active: boolean;
  type: string;
}

function Coins() {
  //state를 이용해 coins를 만들어 준다
  const [coins, setCoins] = useState<CoinInterface[]>([]);
  const [loading, setLoading] = useState(true);
  //state가 coins으로 이루어진 array라는 것을 알려주기 위해<interface>작성
  useEffect(() => {
    (async () => {
      const response = await fetch('https://api.coinpaprika.com/v1/coins');
      const json = await response.json();
      setCoins(json.slice(0, 100));
      setLoading(false);
    })();
  }, []);
  return (
    <Container>
      <Header>
        <Title>코인</Title>
      </Header>
      {loading ? (
        <Loader>"Loading..."</Loader>
      ) : (
        //loading 이 참이면 Loading... 출력, 거짓이면 CoinsList 보여줌
        <CoinsList>
          {coins.map((coin) => (
            <Coin key={coin.id}>
              <Img
                src={`https://cryptoicon-api.vercel.app/api/icon/${coin.symbol.toLowerCase()}`}
              />

              <Link
                to={{
                  pathname: `/${coin.id}`,
                  state: { name: coin.name },
                  //Link를 이용해 string 이외에 더 많은 데이터를 보낼 수 있다
                }}
              >
                {coin.id}
              </Link>
            </Coin>
          ))}
        </CoinsList>
      )}
    </Container>
  );
}

export default Coins;

Coin

import styled from 'styled-components';
import { useEffect, useState } from 'react';
import { useLocation, useParams } from 'react-router';

//useParams 는 URL에서 관심있어 하는 정보를 잡아낼 수 있게 해준다.

function Coin() {
  const [loading, setLoading] = useState(true);
  //state가 coins으로 이루어진 array라는 것을 알려주기 위해<interface>작성

  //Coins 에서 보내는 state 를 사용하기 위해 useLocation 이라는 hook을 사용해서 받아와보자! react-router-dom이 보내주는
  // location object에 접근하기만 하면 된다.
  const { coinId } = useParams<RouteParams>();
  const { state } = useLocation<RouteState>();
  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);
    })();
  }, []);

  const [info, setInfo] = useState({});
  const [priceInfo, setPriceInfo] = useState({});

  return (
    <Container>
      <Header>
        <Title>{state?.name || 'Loading'}</Title>
      </Header>
      {loading ? <Loader>"Loading..."</Loader> : null}
    </Container>
  );
}

interface RouteState {
  name: string;
}

interface RouteParams {
  coinId: string;
}

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;
}

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: 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;
    };
  };
}

const Container = styled.div`
  padding: 0px 20px;
  max-width: 480px;
  margin: 0 auto;
`;

const Header = styled.header`
  height: 20vh;
  display: flex;
  justify-content: center;
  align-items: center;
`;

const Title = styled.h1`
  font-size: 50px;
  color: ${(props) => props.theme.accentColor};
`;

const Loader = styled.span`
  display: block;
  text-align: center;
`;

export default Coin;
profile
최강 프론트엔드 개발자가 되고싶은 안유진 입니다
post-custom-banner

0개의 댓글