데이터 패칭, 캐싱, 동기화 등이 있다. 이런 작업을 쉽게 해주는게 React-Query이다. 근데 무조건 React-Query를 사용해야지만 할 수 있을까? 그냥 React로만은 불가능할까? 답은 아니다! React로도 해줄수는 있다.
useState, useCallBack, useEffect 조합으로 가능! refetch 까지 가능
const [data, setData] = useState(null);
const fetch = useCallback(()=>{...},[]);
useEffect(()=>{fetch();},[]);
return { data, refetch: fetch };
context api 조합으로 가능!
const CacheContext = React.createContext(null);
const {Provider} = CacheContext;
function CacheProvider({children}) {
const [cache, setCache] = useState({});
...
return <Provider value={value}>{children}</Provider>
}
여러가지 트릭을 이용해 사용자가 인지하는 순간 데이터를 새로 가져오도록 되어있다. 그래서 setInterval 함수와 useEffect 조합으로 특정시간 또는 특정 조건으로 데이터를 새로 가져오게 할 수 있다.
useEffect(()=>{
const interval = setInterval(handleFocus, chcheTime)
window.addEventListener('focus', handleFocus, false);
...
return () +> {
clearInterval(interval);
window.removeEventListener('focus', handleFocus, false);
...
}
}, [])
이렇게 구현할 경우 복잡하고 테스트와 시간이 필요하게 됩니다. 그렇기 때문에 안정성을 확보하기 어렵고.. 시간과 노력이 필요하다..😭 그리고 useCallback, useEffect, useState, Context API 등등 고려해야 할 사항이 너무 많다. 반면!! React-Query를 사용하게 되면 QueryClient(Context), useQuery, useMutation 이 3가지로 간단하게 구현할 수 있다.
그 이유는 크게 아래의 3가지로 나눌수 있습니다. 🤓
Redux 자체는 사실상 비동기 처리를 위한 상태관리 라이브러리가 아니라여서 Redux-Saga와 같은 별도 미들웨어를 사용하지 않으면 비동기 처리가 불가능하다.
Redux-Saga에서 api를 받아온후 Redux에 상태를 저장하는데, 이때 api의 상태에 따라 랜더링을 해줘야 할때가 있다.(예를 들어보면 isLoding, isSuccess, isError) 그런데!! Redux-Saga는 이런 상태에 관한 정보를 주지 않는다...😱 따라서 따로 상태를 관리해주어야 한다!
그런데 React-Query는 이 옵션을 기본으로 제공해준다!
Redux에서는 하나의 api가 추가된다면 actions + Reducers + Sagas 세트를 추가해주어야 한다. 그리고 각각의 Sagas에 dependency가 있을 경우 관리해주기 어렵다.
반면 react query를 사용하면 querykey나 enabled option을 주어서 좀 더 직관적으로 관리 할 수 있다.
redux에 담겨있는 데이터는 서버사이드 데이터와 클라이언트 사이드 데이터가 섞여있습니다. 따라서 데이터를 구분하기 어렵다는 단점이 존재했습니다. 이를 클라이언트 사이드 데이터는 Context API(constate, recoil, redux)로 분리했고, 서버사이드 데이터는 React-Query(RTK-Query, Apollo, SWR)으로 분리하여 좀 더 데이터 구분이 명확하게 개선할 수 있습니다.
만약 api 처리후 에러가 발생했을 경우 redux를 사용하게 되면 useEffect를 사용해서 에러처리를 해주어야 합니다. 에러처리의 경우 saga에서 한번에 처리해주어도 되지만, 만약 각각 사용하는 component에서 같은 api의 에러처리를 다르게 해야하는 경우가 있기 때문에 이러한 상황도 고려하여 useEffect로 처리해주어야 합니다.
useEffect(()=>{
action.fetch결제정보();
})
useEffect(()=>{
//에러처리
if(loadStatus?.fetch결제정보?.error){
actions.fetching('fetch결제정보');
history.replace("/");
}
},[loadStatus?.fetch결제정보?.error]);
그렇게 때문에 아래와 같은 복잡한 구조를 가지게 됩니다.
반면! react-query를 사용한다면 onError 함수를 처리할 수 있습니다!!!(완전 간단😄👍)
출처: 카카오 dev 2022