[React-Query] 리액트 쿼리 기본 개념 staleTime, cacheTime, useQuery, useMutation

제론·2022년 9월 10일
1

#React

목록 보기
9/11
post-thumbnail

Client State

  • 웹 브라우저 세션과 관련된 모든 정보
    • ex) 언어 선택, 다크모드 등과 같이 서버에 일과 관련X

Server State

  • 서버에 저장되지만 클라이언트에 표시하는데 필요한 데이터
    • ex) 블로그 게시글

React Query

기능

  • 서버 데이터 캐시를 관리
    • 서버 데이터 필요시 fetch, axios가 아닌 React Query 캐시 요청
    • 클라이언트 구성에 따라 해당 캐시를 유지 관리
  • 클라이언트 캐시 데이터와 서버 데이터 비교
    1. 명령형 처리 - 쿼리 클라이언트에 데이터 무효화 하고 캐시를 교체할 새 데이터 서버에서 가져옴
    2. 선언형 처리 - refatch를 트리거 하는 조건 구성
  • 서버에 대한 모든 쿼리의 로딩 및 오류 상태 유지 시켜줌
  • Prefetch - 페이지네이션, 무한스크롤에 따른 데이터를 조각으로 가져올 수 있는 기능
  • 중복 요청 제거
  • 서버 오류시 재시도 관리
  • 쿼리 성공 오류시 조치할 수 있는 콜백 전달

Getting Started

  • 쿼리 클라이언트 만들기
    • 쿼리와 데이터 캐시를 관리하는 클라이언트
  • 쿼리 프로바이더 만들기
    • 자식 컴포넌트에 캐시와 클라이언트 구성을 제공
  • useQuery 훅 사용
    • 서버에서 데이터 가져오기
    • useQuery 반환 데이터
      • data, isLoading, isError, isFetching, error …
      • isLoading과 isFetching의 차이 ⇒ 캐시데이터 존재여부
        • isFetching - async 쿼리 함수가 아직 resloved 되지 않은 상태(아직 데이터를 가져오는 중)
        • isLoading - isFetching이 true이면서 캐시데이터 없음
        • 페이지네이션 구현할때 사용하게 됨
      • isError
        • 에러 발생시 3번의 시도를 하고 isError가 true가 됨
      • error
        • 어떤 에러인지, 에러 반환 객체
      • onError
  • staleTime
    • 데이터를 허용하는 최대나이라고 볼 수 있음⇒ 데이터가 만료됐다고 판단하기 전까지 허용하는 시간
    • re-fatching할 때 고려해야할 사항
    • staleTime의 디폴트 값은 왜 0일까
      • 데이터는 항상 만료된 상태이므로 서버에서 다시 가져와야 한다고 가정한다는 뜻
      • 실수로 클라이언트에게 만료된 데이터를 제공할 가능성이 훨씬 줄어든다
  • cacheTime
    • 데이터가 비활성화된 이후 남아 있는 시간
    • cache - 나중에 다시 필요할 수도 있는 데이터
    • 활성화된 useQuery가 존재하지 않는다면 쿼리는 cold storage로 이동한다
    • 캐시 유효시간의 기본값은 5분
    • 캐시 유효시간이 지나면 가비지 컬렉터에 의해 데이터는 삭제됨
    • 캐시는 fetching 해서 최신데이를 가져올 동안 보여주는 데이터

Query key

  • 쿼리키가 동일한 요청을 보내면 데이터는 업데이트 되지 않고 계속 쌓임
  • 어떠한 트리거가 있어야만 데이터를 refatch한다
    • 트리거 💡 1. 컴포넌트 마운트 2. 윈도우창 re-focus 3. refecth 함수 4. 자동 refetch - 시간 설정 5. mutation 이후에 query invlidate
  • 문제상황
    게시글 클릭시 기존 댓글에 대한 캐시가 남아있어 댓글 내용이 쌓인다.
  • 해결책 - 게시물에 대한 쿼리에 라벨을 설정
    • query key를 배열로 전달
    • [’comments’, post.id]
    • ⇒ 쿼리키를 쿼리에 의존성 배열로 취급 ⇒ post.id가 업데이트 되면 새로운 쿼리 생성, 의존생 배열이 다르다면 완전히 다른 쿼리로 인식함
    • 개발자 도구 확인시 기존 쿼리는 비활성화 되고 캐시에서 지워지지는 않음 - 캐시시간 만료되면 캐시에서 제거됨

React Query Pagination

  • 페이지마다 다른 쿼리키가 필요
  • 버튼 클릭시 currentPage 상태 업데이트 → 새로운 쿼리 실행하여 새로운 페이지 표시
  • 로딩 인디케이터가 안나오게 → Prefetching!!

Prefetching

  • 캐시를 추가하여 미리 fetching 해오게 하는 기능
useEffect(() => {
    if (currentPage < maxPostPage) {
      const nextPage = currentPage + 1
      queryClient.prefetchQuery(['posts', nextPage], () => fetchPosts(nextPage), {
        staleTime: 2000,
        // 이전 페이지로 돌아갔을 때 캐시에 해당 지난 데이터가 있도록
        keepPreviousData: true
      })
    }
  }, [currentPage, queryClient])
  • 작동 방식 예시 - pagination
    • currentPage가 4페이지로 바뀔 때 캐시에 4페이지가 있는지 물음
    • prefetching 했기 때문에 캐시에 존재하지만 자동으로 stale상태가 적용됨
    • 따라서 fetchPosts를 실행하고 다른 데이터가 반환된다면 바뀐 데이터로 기존의 데이터를 업데이트한다.
    • fetchPosts가 동작하고 있는 중에는 기존 데이터를 표시
    • 데이터를 최신상태로 유지하기 위해 서버와 데이터 변화를 확인했다는 사실을 사용자 입장에서는 모름

Mutation

  • 서버에 데이터를 업데이트 하도록 서버에 네트워크 호출 = Delete, Patch, Put
  • 서버에서 반환받은 데이터로 리액트 쿼리 캐시 데이터를 업데이트한다.
  • 관련된 쿼리를 무효화 할 수 있음
  • 무효화 하는 경우 데이터를 refetch해서 데이터를 최신상태로 유지

useMutation

  • mutation함수 반환, 쿼리키X
  • isFeching 없음
  • useQuery는 데이터 fetching 실패시 retry 3번이 있지만 mutation디폴트값은 retry가 없고 따로 설정 해야 함
const deleteMutation = useMutation((postId) => deletePost(postId))

{deleteMutation.isError && <p style={{ color: 'red' }}>Error deleting the post</p>}
{deleteMutation.isLoading && <p style={{ color: 'purple' }}>deleting the post</p>}
{deleteMutation.isSuccess && <p style={{ color: 'green' }}>Post has (not) been deleted</p>}
<button onClick={deleteMutation.mutate(post.id)}>Delete</button>
profile
Software Developer

0개의 댓글