Fetch: JavaScript 내장 라이브러리.
promise 기반으로 만들어졌기에 Axios와 마찬가지로 데이터를 다루는데 어렵지 않다.
Axios: 네트워크 요청을 위해 fetch() 라는 메서드를 제공하는 인터페이스. 따로 설치할 필요가 없다.
node.js와 브라우저를 위한 HTTP통신 라이브러리.비동기로 HTTP 통신을 가능하게 해주며 return을 promise 객체로 해주기때문에 response 데이터를 다루기도 쉽다.
Axios의 post method구현
axios({
method: 'post',
url: '/user/12345',
data:{
firstName: 'bibin'
lastName: 'Mun'
}
});
리액트 애플리케이션에서 서버 상태 가져오기, 캐싱, 동기화 및 업데이트를 보다 쉽게 다를 수 있도록 도와주며 클라이언트 상태와 서버 상태를 명확히 구분하기 위해서 만들어진 라이브러리
react-query에서 기존 상태 관리 라이브러리(redux, mobX)는 클라이언트 상태 작업에 적합하지만 비동기 또는 서버 상태 작업에는 그다지 좋지 않다.
Client State와 Server State는 완전히 다르며
Client는 컴포넌트에서 관리하는 각각의 input값으로 예를 들 수 있고,
Server는 database에 저장되어있는 데이터로 예를 들수 있다.
store에 클라이언트 데이터와 서버 데이터가 공존하게 된다.
그 데이터가 서로 상호작용하면서 서버도 클라이언트도 아닌 혼종이 된다.
그래서 서버,클라이언트 데이터를 분리한다.
react-query 장점
- 캐싱
- get을 한 데이터에 대해 update를 하면 자동으로 get을 다시 수행한다.(ex.게시판의 글을 가져왔을 때 게시판의 글을 생성하면 게시판 글을 get하는 api를 자동으로 실행)
- 데이터가 오래 되었다고 판단되면 다시 get(invalidateQueries)
- 동일 데이터 여러번 요청하면 한번만 요청한다.(옵션에 따라 중복 호출 허용 시간 조절 가능)
- 무한스크롤
- 비동기 과정을 선언적으로 관리할 수 있다.
- react hook과 사용하는 구조가 비슷하다.
useQuery
- 데이터를 get하기 위한 api. post, update는 useMutation을 사용한다.
- 첫번째 parameter로 unique key가 들어가고, 두번째는 비동기함수(api호출 함수)가 들어간다.
(두번째는 당연히 promise)- 첫번째 파라미터로 설정한 unique key는 다른 컴포넌트에서도 해당 키를 사용하면 호출가능.
unique key는 String과 배열을 받는다. 배열로 넘기면 0번 값은 string값으로 다른 컴포넌트에서 부를 값이 들어가고 두번째 값을 넣으면 query함수 내부에 파라미터로 해당 값이 전달된다.- return 값은 api의 성공, 실패여부, api return값을 포함한 객체이다.
- useQuery는 비동기로 작동한다. 즉, 한 컴포넌트에 여러개의 useQuery가 있다면 하나가 끝나고 다음 useQuery가 실행되는 것이 아닌 두개의 useQuery가 동시에 실행된다. 여러개의 useQuery가 있따면 useQueries를 써라.
- enabled를 사용하면 useQuery를 동기적으로 사용 가능하다.
ex)
const Todos = () => {
const { isLoading, isError, data, error } = useQuery("todos", fetchTodoList, {
refetchOnWindowFocus: false, // react-query는 사용자가 사용하는 윈도우가 다른 곳을 갔다가 다시 화면으로 돌아오면 이 함수를 재실행합니다. 그 재실행 여부 옵션 입니다.
retry: 0, // 실패시 재호출 몇번 할지
onSuccess: data => {
// 성공시 호출
console.log(data);
},
onError: e => {
// 실패시 호출 (401, 404 같은 error가 아니라 정말 api 호출이 실패한 경우만 호출됩니다.)
// 강제로 에러 발생시키려면 api단에서 throw Error 날립니다. (참조: https://react-query.tanstack.com/guides/query-functions#usage-with-fetch-and-other-clients-that-do-not-throw-by-default)
console.log(e.message);
}
});
if (isLoading) {
return <span>Loading...</span>;
}
if (isError) {
return <span>Error: {error.message}</span>;
}
return (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
};
-isLoading, isSuccess말고 status로 한번에 처리 가능.
function Todos() {
const { status, data, error } = useQuery("todos", fetchTodoList);
if (status === "loading") {
return <span>Loading...</span>;
}
if (status === "error") {
return <span>Error: {error.message}</span>;
}
return (
<ul>
{data.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}