(
+ ["ohlcv", coinId],
+ () => fetchCoinHistory(coinId),
+ {
+ refetchInterval: 1000000,
+ },
+ );
+ const isError = !Array.isArray(data);
+ return (
+
+ {isLoading ? (
+ "Loading Chart"
+ ) : isError ? (
+
값이 존재하지 않습니다..😭
+ ) : (
+ Number(price.close)) ?? [],
+ },
+ ]}
+ options={{
+ theme: {
+ mode: "dark",
+ },
+ chart: {
+ height: 400,
+ width: 500,
+ toolbar: {
+ show: false,
+ },
+ background: "transparent",
+ },
+ grid: { show: false },
+ stroke: {
+ width: 5,
+ },
+ yaxis: { show: false },
+ xaxis: {
+ labels: { show: false },
+ axisTicks: { show: false },
+ axisBorder: { show: false },
+ type: "datetime",
+ categories:
+ data?.map((price) =>
+ new Date(Number(price.time_close) * 1000).toUTCString(),
+ ) ?? [],
+ },
+ fill: {
+ type: "gradient",
+ gradient: { gradientToColors: ["#0be881"], stops: [0, 100] },
+ },
+ colors: ["#0fbcf9"],
+ tooltip: {
+ y: {
+ formatter: (value) => `$ ${value.toFixed(2)}`,
+ },
+ },
+ }}
+ />
+ )}
+
+ );
}
diff --git a/src/routes/Coin.tsx b/src/routes/Coin.tsx
index c5931d8..a6ed2a0 100644
--- a/src/routes/Coin.tsx
+++ b/src/routes/Coin.tsx
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from "react";
+import { Helmet } from "react-helmet";
import {
Link,
Route,
@@ -10,6 +11,8 @@ import {
import { styled } from "styled-components";
import Price from "./Price";
import Chart from "./Chart";
+import { useQuery } from "react-query";
+import { fetchCoinInfo, fetchCoinTickers } from "../api";
const Container = styled.div`
padding: 0px 20px;
@@ -41,9 +44,10 @@ const Loader = styled.h1`
const Overview = styled.div`
display: flex;
- justify-content: space-between;
+ justify-content: space-around;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
+ margin: 15px 0px;
border-radius: 10px;
`;
const OverviewItem = styled.div`
@@ -59,6 +63,9 @@ const OverviewItem = styled.div`
`;
const Description = styled.p`
margin: 20px 0px;
+ background-color: rgba(0, 0, 0, 0.5);
+ padding: 10px 20px;
+ border-radius: 10px;
`;
const Tabs = styled.div`
@@ -68,7 +75,7 @@ const Tabs = styled.div`
gap: 10px;
`;
-const Tab = styled.span<{ isActive: boolean }>`
+const Tab = styled.span<{ $isActive: boolean }>`
text-align: center;
text-transform: uppercase;
font-size: 12px;
@@ -77,7 +84,7 @@ const Tab = styled.span<{ isActive: boolean }>`
padding: 7px 0px;
border-radius: 10px;
color: ${(props) =>
- props.isActive ? props.theme.accentColor : props.theme.textColor};
+ props.$isActive ? props.theme.accentColor : props.theme.textColor};
a {
display: block;
}
@@ -147,32 +154,41 @@ interface PriceData {
}
function Coin() {
- const [loading, setLoading] = useState(true);
const { coinId } = useParams();
const { state } = useLocation();
- const [info, setInfo] = useState();
- const [priceInfo, setPriceInfo] = useState();
const priceMatch = useRouteMatch("/:coinId/price");
const chartMatch = useRouteMatch("/:coinId/chart");
- useEffect(() => {
- (async () => {
- const infoData = await (
- await fetch(`https://api.coinpaprika.com/v1/coins/${coinId}`)
- ).json();
- console.log(infoData);
- setInfo(infoData);
- const priceData = await (
- await fetch(`https://api.coinpaprika.com/v1/tickers/${coinId}`)
- ).json();
- setPriceInfo(priceData);
- setLoading(false);
- })();
- }, []);
+ const { isLoading: infoLoading, data: infoData } = useQuery(
+ ["info", coinId],
+ () => fetchCoinInfo(coinId),
+ );
+ const { isLoading: tickersLoading, data: tickerData } = useQuery(
+ ["tickers", coinId],
+ () => fetchCoinTickers(coinId),
+ {
+ refetchInterval: 10000000,
+ },
+ );
+
+ const loading = infoLoading && tickersLoading;
return (
+
+
+ {state?.name
+ ? state.name
+ : loading
+ ? "코인 로딩중..."
+ : infoData?.name}
+
+
- {state?.name ? state.name : loading ? "코인 로딩중..." : info?.name}
+ {state?.name
+ ? state.name
+ : loading
+ ? "코인 로딩중..."
+ : infoData?.name}
{loading ? (
@@ -181,35 +197,35 @@ function Coin() {
<>
- Rank:
- {info?.rank}
+ 심볼
+ ${infoData?.symbol}
- Symbol:
- ${info?.symbol}
+ 순위
+ {infoData?.rank}
- Open Source:
- {info?.open_source ? "Yes" : "No"}
+ 가격
+ {tickerData?.quotes.USD.price.toFixed(2)}
- {info?.description}
- Total Suply:
- {priceInfo?.total_supply}
+ 총량
+ {tickerData?.total_supply}
- Max Supply:
- {priceInfo?.max_supply}
+ 최대 발행량
+ {tickerData?.max_supply}
+ {infoData?.description}
-
+
Chart
-
+
Price
@@ -219,7 +235,7 @@ function Coin() {
-
+
>
diff --git a/src/routes/Coins.tsx b/src/routes/Coins.tsx
index d4ab511..629d2e6 100644
--- a/src/routes/Coins.tsx
+++ b/src/routes/Coins.tsx
@@ -1,6 +1,9 @@
import React, { useEffect, useState } from "react";
+import { useQueries, useQuery } from "react-query";
import { Link } from "react-router-dom";
import { styled } from "styled-components";
+import { fetchCoins } from "../api";
+import { Helmet } from "react-helmet";
const Container = styled.div`
padding: 0px 20px;
@@ -56,7 +59,7 @@ const Img = styled.img`
margin-right: 20px;
`;
-interface CoinInterface {
+interface ICoin {
id: string;
name: string;
symbol: string;
@@ -67,26 +70,20 @@ interface CoinInterface {
}
function Coins() {
- const [coins, setCoins] = useState([]);
- 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);
- })();
- }, []);
+ const { isLoading, data } = useQuery("allCoins", fetchCoins);
return (
+
+ Coins
+
- {loading ? (
+ {isLoading ? (
😫loading😫
) : (
- {coins.map((coin) => (
+ {data?.slice(0, 100).map((coin) => (