[내일배움캠프 TIL] 50일차

Jaehyeon Ye·2023년 1월 6일
0

오늘 새로 배운 것

React Query(2)

어제 TIL에서 잠깐 다루었지만 다시 다른 말로 정리하면,
React Query가 다루는 서버 상태(Server State)는 FE에서 다루는 화면 View를 위한 데이터가 아닌 API 에서 가지고 온 데이터를 말한다.

쿼리 키의 상태 흐름

1 데이터 요청을 하는 흐름 - fetching
2 응답 받아온 직후 상태 - fresh

3 fresh 한 데이터가 들어왔는데 일정 시간(staleTime)이 지나면 상함 - stale
fresh 한 시간을 유지해주기 위해서 staleTime을 useQuery의 옵션 속성에 지정할 수 있음

const query = useQuery('query_key', getList, {
    onSuccess: (data) => {
      console.log(data);
    },
    staleTime: 3000, //fresh 시간 3초
  });

그래도 여기까지는 데이터가 사용하는 상태 - active

4 쿼리를 더이상 사용하지 않는 - inactive
쿼리가 unmount된 상태. 쿼리가 unmount됐다고 해서 없어지는 게 아니라 캐시 데이터가 남아있다.

5 캐시데이터가 완전히 캐시 메모리에서까지 완전히 삭제되면 그걸 - delete

정리하면, fetching - fresh - stale - inactive - delete 의 흐름이다.

Query 개념이 가장 중요한데 redux에서 말하는 store 정도의 개념으로 일단 이해하면 된다.
쿼리는 쿼리 key값이 있고 query function이 있다. (어제 말했던 fetcher 함수)
쿼리 키가 어딘가에 호출이 되는데 이 키를 갖고있는게 변하면 api 요청을 다시 함
우리가 redux 쓸때는 우리가 임의로 뭔가 작업해주지 않으면 절대 store 안에 데이터는 바뀌지 않는데 쿼리는 다르다.

키값에 엮여있는 뭔가 바뀌게 되면 다시 api 요청해서 같은 키값에 있는 데이터를 바꾼다.
브라우저 창 바깥으로 포커스를 이동했다가 다시 들어오면 다시 요청해서 데이터를 받아온다.
페이지를 벗어났다가 들어오면 그러는데 stale이기 때문에 그렇다. Fresh time을 늘려주면 된다.
staleTime을 길게 하면 fresh 상태에서 길게 가는데, fresh 상태에서는 페이지를 전환하고 와도 요청을 다시 하지 않는다.

쿼리는 옵션 값에 따라 알아서 하니까 서버를 최신 상태로 관리하기가 편하다.

const query = useQuery(쿼리키, 페쳐, 옵션)

주의할 점은 한개의 쿼리 인스턴스를 다섯번 호출한다고 해도 query 키가 같으면 fetcher를 한번만 호출한다.
그런데 옵션에 있는 onSuccess를 다섯번 호출한다.
그말인즉슨 쿼리 인스턴스 자체는 한번만 불려도 옵션에 넣은 것은 여러번 호출된다.

리액트 쿼리의 또 하나의 장점은 어제 살펴본대로 isLoading 상태 관리를 위한 state를 따로 만들 필요 없다. 알아서 관리해준다.

queryClient.invalidateQueries

화면 View 에 쿼리 키에 해당하는 데이터를 즉각 반영되게 하려면 캐시 데이터를 건드려 줘야한다.
처음에는 react query를 배우기 전처럼 useEffect를 써서 해당 데이터를 담은 list라는 쿼리 key를 dependency array에 넣고 useEffect 안에 getlist() 해주면 되는 줄 알았다. 하지만 해보니까 즉각 화면에 반영되지 않았다.
화면에 즉각 보여주게 하려면 알고보니 useEffect를 쓸 게 아니라 쿼리 관련 훅의 옵션에 캐시 데이터를 건드리는 후처리를 해주어야 했다. list에 요소를 추가하는 useMutation의 옵션에 클라이언트 요청이 Success할 경우의 onSuccess를 넣어주고 그 안에 queryClient.invalidateQueries(‘쿼리키’) 넣어줘야했다.

const { mutate } = useMutation(list에 새 요소 추가하는 함수, {
    // 데이터 목록 즉각 화면에 불러오기
    onSuccess: () => {
      queryClient.invalidateQueries('list');
      ...
    },
  });

왜 이렇게 해야하냐면, 일단 쿼리가 stale 되면 이 키에 엮인 데이터는 못 쓰는 데이터가 된다. 현재 클라이언트가 붙들고 있는 이 쿼리 키에 해당하는 데이터는 내가 추가요청을 보낸 순간 old해져버린다. 그래서 이 쿼리를 무효화시켜줘야하는데 그 역할을 하는게 바로 위에 queryClient.invalidateQueries(‘old한 쿼리 키’)이기 때문에 이걸 사용해주는 것이다. 주의할 점은 invalidateQueries안에 key값 안 넣으면 모든 쿼리가 다 날아간다. 즉 모든 쿼리가 다 무효화된다. key값을 꼭 넣어줘야한다.

Suspense

로딩 중일 때(isLoading) 상태를 화면에 표시하도록 해주는 기능

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
    },
  },
});

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.Suspense fallback={<div>화면을 불러오는 중입니다...</div>}>
    <QueryClientProvider client={queryClient}>
      <ReactQueryDevtools initialIsOpen={true} />
      <App />
    </QueryClientProvider>
  </React.Suspense>
);

결과화면은 fallback 안에 있는 div 요소의 텍스트가 출력된다.

profile
FE Developer

0개의 댓글