Crypto_Tracker: 02

김정훈·2023년 7월 23일
0
post-thumbnail
post-custom-banner

ReactQuery

: 리액트 쿼리는 데이터를 캐시에 저장해둔다.

npm i @tanstack/react-query
npm install @tanstack/react-query-devtools

그리고 index.tsx에 다음과 같이 설정해주자.

import ReactDOM from "react-dom/client";
import { ThemeProvider } from "styled-components";
import App from "./App";
import { theme } from "./theme";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);

const queryClient = new QueryClient();

root.render(
  <>
    <QueryClientProvider client={queryClient}>
      <ThemeProvider theme={theme}>
        <App />
      </ThemeProvider>
    </QueryClientProvider>
  </>
);

ReactQuery을 사용해서 이 부분을 바꿔본다.(Coins.tsx)

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

api.ts파일을 하나 만들자(async await에서 promise로 바꿈)
: fetchCoins는 fetch함수를 부른다
→ fetch함수는 URL로부터 json을 return할 것이다.
→ 이 return한 값은 결국 useQuery의 data값으로 담긴다.

export function fetchCoins() {
  return fetch("https://api.coinpaprika.com/v1/coins").then((response) =>
    response.json()
  );
}

Coins.tsx

  • useQuery: 두 개의 argument를 받는다.
    1. query의 고유 식별자 - key
    2. fetcher 함수
      그러면 return 값을 보자.
      isLoading이라고 하는 boolean값을 return 하는데 기존의 Loading State을 대체할 수 있다.
      그리고 두 번째는 fetcher 함수의 결과값을 담아준다.
const {isLoading, data} = useQuery<ICoin[]>(["allCoins"], fetchCoins);

App.tsx에 ReactQueryDevtools를 render한다.

import {ReactQueryDevtools} from "@tanstack/react-query-devtools";

function App(){
	return(
	<>
		<ReactQueryDevtools initialIsOpen={true} />
	</>
	)
}

Coin.tsx부분도 바꿔보자
: 크게 다른 부분은 없고, 두 개의 useQuery을 사용하기 때문에, 고유한 값을 설정해줘야 한다.

  const [loading, setLoading] = useState(true);
  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); API값 정의하기 위한 console.log
      const priceData = await (
        await fetch(`https://api.coinpaprika.com/v1/tickers/${coinId}/`)
      ).json();
      // console.log(priceData); API값 정의하기 위한 console.log
      setInfo(infoData);
      setPriceInfo(priceData);
      setLoading(false);
    })();
  }, [coinId]);

fetch부분은 api.ts파일로 옮긴다.(async await에서 promise로 바꿈)

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

export function fetchCoinInfo(coinId: string) {
  return fetch(`${BASE_URL}/coins/${coinId}`).then((response) => response.json());
}
export function fetchCoinTickers(coinId:string) {
    return fetch(`${BASE_URL}/tickers/${coinId}`).then((response) => response.json());
}

Coin.tsx
loading부분은 아예 필요가 없어진다. → useQuery에서 제공하기 때문.
키값과 가져오는 값이 중복되면 안되기 때문에 다음과 같이 다 수정해줌.(infoLoading, infoData, info)

const { coinId } = useParams<RouteParams>();
// 이 coinId을 useQuery의 키값으로 사용한다.

const {isLoading:infoLoading, data:infoData} = useQuery<InfoData>(["info",coinId], () => fetchCoinInfo(coinId));

const {isLoading:tickersLoading, data:tickerData} = useQuery<PriceData>(["tickers",coinId], () => fetchCoinTickers(coinId));
profile
WebDeveloper
post-custom-banner

0개의 댓글