Crypto Tracker 4.12 _ Price Chart part Two

Eugenius1st·2022년 4월 8일
0

ReactJS_MasterClass

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

API에서 받아온 data 시각화 하기

APEXCHART 사용

APEXCHAR란 자바스크립트 chart library 이다.

다양한 차트가 있다.

사용하기 위해선 명령어를 실행시켜야 한다.

intergrations 에서 react 꺼로 들어가서 npm install 한다.

npm install --save react-apexcharts apexcharts

그리고 그 전에 typescript에게 data가 어떻게 생겼는지 말을 해줘야 한다.

API가 준 값을 알려주자.
인터페이스로 API의 타입을 정의해준다

그리고 apex를 import 한 후 다양한 옵션들을 설정해 주면


이러한 차트가 나타나게 된다.

즉 어떤 옵션이 들어가야하는지만 안다면 원하는 대로 차트를 꾸밀 수 있는 것이다.

이는 사이트의 options 에서 확인할 수 있다.

Chart.tsx

import { useQuery } from 'react-query';
import { fetchCoinHistory } from './api';
import ApexChart from 'react-apexcharts';

interface IHistorycal {
  time_open: string;
  time_close: string;
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
  market_cap: number;
}

interface ChartProps {
  coinId: string;
}

function Chart({ coinId }: ChartProps) {
  const { isLoading, data } = useQuery<IHistorycal[]>(['ohlcv', coinId], () =>
    fetchCoinHistory(coinId)
  );
  //14개를 받아와야 하므로 배열로 전달.
  return (
    <div>
      {isLoading ? (
        'Loading chart...'
      ) : (
        <ApexChart
          type="line"
          series={[
            {
              name: 'price',
              data: data?.map((price) => price.close) as number[],

              // 맵함수는 리턴하는 값으로 array를 만들어 준다.
              //as 를 이용하셔도 됩니다. 저 데이터는 number 배열이다! 라고강제함.
              // 맵함수는 리턴하는 값으로 array를 만들어 준다.
            },
          ]}
          //series는 보내고 싶은 모든 data가 들어있다.
          options={{
            theme: { mode: 'dark' },
            chart: {
              width: 500,
              height: 300,
              toolbar: { show: false },
              background: 'transparents',
            },
            grid: { show: false },
            stroke: { curve: 'smooth', width: 3 },
            yaxis: { show: false },
            xaxis: {
              labels: { show: false },
              axisTicks: { show: false },
              axisBorder: { show: false },
            },
          }}
        />
        //apexvhart는 위와같이 다양한 옵션이 있다.
      )}
    </div>
  );
}
// const params = useParams();
// console.log(params);
//coinId 가져오기 또는 서브 Router 에서 porps로 받아오기
export default Chart;

##Coins.tsx

import styled from 'styled-components';
import { Link } from 'react-router-dom';
import { useQuery } from 'react-query';
import { fetchCoins } from './api';
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 ICoin {
  id: string;
  name: string;
  symbol: string;
  rank: number;
  is_new: boolean;
  is_active: boolean;
  type: string;
}

function Coins() {
  const { isLoading, data } = useQuery<ICoin[]>('allCoins', fetchCoins);
  console.log(isLoading, data);
  //useQery는 두개의 식별자가 필요하다. 첫번째는 고유식별자, 두번째는 fetcher함수이다.
  // useQuery는 isLoading 이라고 불리는 boolean값을 return하는데 이전에 있던
  // const[lading,setLoading]과 setLoading(false)를 대체할 수 있는 것이다.
  // 총 설명: useQuery hook에서 fetcher함수 fetchCoins를 불러오고 그함수가
  // isLoading 즉, fetcher함수가 끝난다면 react Query가 말해줄 것이다.
  // 그리고 return 값을 data에 넣어줄 것이다. 아래에서 state에 넣었던 것처럼..
  // +) data 타입을 명시하기 위해 <CoinInterface[]>를 넣어준다.

  // 위 코드와 아래 코드는 같다.

  // const [coins, setCoins] = useState<CoinInterface[]>([]);
  // 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, 100));
  //     setLoading(false);
  //   })();
  // }, []);

  return (
    <Container>
      <Header>
        <Title>코인</Title>
      </Header>
      {isLoading ? (
        <Loader>"Loading..."</Loader>
      ) : (
        //loading 이 참이면 Loading... 출력, 거짓이면 CoinsList 보여줌
        <CoinsList>
          {data?.slice(0, 100).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;

api.ts

const BASE_URL = `https://api.coinpaprika.com/v1`;

export async function fetchCoins() {
  // const response = await fetch(`${BASE_URL}/coins`);
  // const json = await response.json();
  // return json;
  //가독성 높은 오래된 방법
  return fetch(`${BASE_URL}/coins`).then((response) => response.json());
  // 두 코드는 같은 것이다. fetcher 함수인 fetchCoin 은 URL을 부르고 URL로 부터 json을 return 한다.
}

export async function fetchCoinInfo(coinId: string) {
  //coinId 타입 명시 필요, coin Id를 fetch하는 함수
  return fetch(`${BASE_URL}/coins/${coinId}`).then((response) => response.json());
}

export async function fetchCoinTickers(coinId: string) {
  //coinId 타입 명시 필요 coin Ticker를 fetch하는 함수
  return fetch(`${BASE_URL}/tickers/${coinId}`).then((response) => response.json());
}

export function fetchCoinHistory(coinId: string) {
  const endDate = Math.floor(Date.now() / 1000);
  const startDate = endDate - 60 * 60 * 24 * 7 * 2;
  return fetch(
    `${BASE_URL}/coins/${coinId}/ohlcv/historical?start=${startDate}&end=${endDate}`
  ).then((response) => response.json());
}
profile
최강 프론트엔드 개발자가 되고싶은 안유진 입니다
post-custom-banner

0개의 댓글