: 리액트 쿼리는 데이터를 캐시에 저장해둔다.
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
boolean
값을 return 하는데 기존의 Loading State
을 대체할 수 있다.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));