본 포스팅은 노마드 코더의 React JS 마스터클래스를 수강한 뒤 작성되었습니다.
<참고 문헌 - React Query 한글 메뉴얼>
https://velog.io/@familyman80/React-Query-%ED%95%9C%EA%B8%80-%EB%A9%94%EB%89%B4%EC%96%BC
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);
const priceData = await (
await fetch(`https://api.coinpaprika.com/v1/tickers/${coinId}`)
).json();
console.log(priceData);
setInfo(infoData);
setPriceInfo(priceData);
setLoading(false);
})();
}, [coinId]);
BUT!! 우리는 이제 이렇게 할 필요가 X.
위에 有는 코드들을 다 삭제해도 됨.
npm i react-query
❗ 아래에 작성되는 모든 것들은 index.tsx에서 진행됨. (react query를 사용하기 위한 install이라고 생각하면 됨)
(1) queryClient 만들기
const queryClient = new QueryClient()
(2) provider 만들기
- 우리가 themeProvider에서 했던 것과 비슷
- QueryClientProvider안에 있는 모든 것은 queryClient에 접근 가능!
return (
<QueryClientProvider client={queryClient}>
<Todos />
</QueryClientProvider>
index.tsx 전체 코드
import React from "react";
import ReactDOM from "react-dom";
import { ThemeProvider } from "styled-components";
import App from "./App";
import { theme } from "./theme";
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient();
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
</QueryClientProvider>
</React.StrictMode>,
document.getElementById("root")
);
1. fetcher 함수 만들기 (fetch를 하는 함수들)
export async function fetchCoin() {
return fetch("내가 원하는 url").then(response => response.json()
);
}
-> 이처럼 우리는 현재 api.tsx라는 타 파일 생성 후, API를 fetch하고 json을 return하는 함수를 만들었음.
2. useQuery를 사용해서 우리가 만들어둔 fetcher 함수 가져오기
const { isLoading, data } = useQuery("allCoins", fetchCoins)
-> useQuery는 fetchCoins 함수를 부르고, 해당 함수가 loading 중이라면 isLoading을 통해 알려줌.
-> fetchCoins 함수가 끝난다면, 해당 함수가 return하는 json 값을 data에 넣음.
∴ 우리가 작업하는 화면 상에서는 위의 한줄로 모든 것을 끝낼 수 있는 것.
export function fetchCoins() {
return fetch("https://api.coinpaprika.com/v1/coins").then((response) =>
response.json()
);
}
import { Link } from "react-router-dom";
import styled from "styled-components";
import { useQuery } from "react-query";
import { fetchCoins } from "./api";
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);
return (
<Container>
<Header>
<Title>코인</Title>
</Header>
{isLoading ? (
<Loader>Loading...</Loader>
) : (
<CoinsList>
{data?.slice(0, 100).map((coin) => (
<Coin key={coin.id}>
<Link
to={{
pathname: `/${coin.id}`,
state: { name: coin.name },
}}
>
<Img
src={`https://coinicons-api.vercel.app/api/icon/${coin.symbol.toLocaleLowerCase()}`}
/>
{coin.name} →
</Link>
</Coin>
))}
</CoinsList>
)}
</Container>
);
}
const Container = styled.div`
padding: 0px 20px;
max-width: 480px;
margin: 0 auto;
`;
const Header = styled.header`
height: 10vh;
display: flex;
justify-content: center;
align-items: center;
`;
const CoinsList = styled.ul``;
const Coin = styled.li`
background-color: white;
color: ${(props) => props.theme.bgColor};
padding: 20px;
border-radius: 15px;
margin-bottom: 10px;
a {
display: flex;
align-items: center;
padding: 20px;
transition: color 0.2s ease-in;
}
&:hover {
a {
color: ${(props) => props.theme.accentColor};
}
}
`;
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: 35px;
height: 35px;
margin-right: 10px;
`;
export default Coins;
Reqct Query를 통해서 API로부터 data를 받아온 경우, 자동적으로 cache에 해당 data들이 저장되어 有
-> 해당 저장된 것을 볼 수 있게 개발자를 위한 도구를 제공하는데 그것이 바로 react query devtools이다.
import { ReactQueryDevtools } from "react-query/devtools";
...
function App() {
return (
<>
<GlobalStyle />
<Router />
<ReactQueryDevtools initialIsOpen={true} />
</>
);
}
이런식으로 현재 저장되어 있는 데이터들이 나옴.
//fetch 함수에 변수를 넘겨줘야 하는 경우
const { isLoading: infoLoading, data: infoData } = useQuery(
["info", coinId],
() => fetchCoinInfo(coinId)
);
// 2개의 함수에서 동일하게 isLoading, data라는 값을 가지면 X되니까, : 를 사용해서 각자 이름을 지정
const { isLoading: tickersLOading, data: tickersData } = useQuery(
["tickers", coinId],
() => fetchCoinInfo(coinId)
);