[React-Query] Section 02

은채·2022년 9월 6일
1
post-thumbnail
post-custom-banner

코드 퀴즈

인자가 필요한 경우

해당 함수로 데이터 패칭하기

const { data, isLoading, isError, error } = useQuery('comments', () =>
    fetchComments(post.id)
  );

() => 함수(인자) 형식으로 구성한다.

docs 예시 :

업데이트

게시물에 따른 댓글 업데이트가 되지 않는다
다른 게시물을 클릭해도

변하지 않는다. 데이터는 만료되었고, 리패칭도 진행하지 않고 있다.

왜?

모든 쿼리가 comments 쿼리 키를 동일하게 사용하고 있어서!!
comments 같이 알려진 쿼리 키가 있을 때는, 어떠한 트리거가 있어야만 데이터를 다시 가져오게 된다.

예시

  • 컴포넌트를 다시 마운트할 때
  • 윈도우를 다시 포커스 할 때
  • useQuery에서 반환되어 수동으로 리패칭을 실행할 때
  • 지정된 간격으로 리페칭을 자동실행할 때
  • 변이를 생성한 뒤 쿼리를 무효화 할 때
  • 클라이언트의 데이터가 서버의 데이터와 불일치할 때

새 블로그 게시물을 클릭하는 것은 위 상황 중 어느것도 맞지 않아 데이터가 만료되어도 불러오지 않는다.

방법

  • 새 블로그 게시물을 클릭 할 때 => 데이터 무효화 ? => 간단하지 않음

  • 데이터를 제거해서는 안됨 ( 블로그 1의 댓글을 캐시에서 제거해서는 안됨 => 같은 쿼리를 실행하는 것이 아니어서 같은 캐시 공간을 차지하지 않는다 - 덮어쓰기 xx )

  • 쿼리는 게시물 id가 포함되어 있어서 쿼리별로 캐시를 남길 수 있다

  • comments 쿼리에 대한 캐시를 공유하지 않아도 된다

  • 각 쿼리에 해당하는 캐시를 갖게 됨

  • 각 게시물에 대한 쿼리에 라벨을 설정하자

  • 쿼리 키에 문자열 대신 배열을 전달하자

  • 쿼리 키를 쿼리에 대한 의존성 배열로 취급하게 된다
  • 쿼리 키가 변경되면 (post.id가 업뎃) => react-query가 새 쿼리를 생성 => staleTime,
    cacheTime을 가지게 되고 => 의존성 배열이 다르면 완전히 다른 것으로 간주

- 데이터를 가져올 때 사용하는 쿼리 함수에 있는 값이 쿼리 키에 포함되어야 함!

useQuery의 쿼리 키에 "comments" 다음 두 번째 요소 Post.id를 추가해서 배열로 만든다.
fetchComments에 전달한 것과 같이!
그렇게 하면 의존성 배열로 작용하여 "comments"에 식별자가 생긴 것과 같다.

제목을 누를 때마다 다른 댓글이 보인다.
전에 눌렀던 것은 cache에 남아있고, catchTime 이후에 가비지로 전환된다

페이지네이션

  • current Page state를 통해 현재페이지를 파악하는 스타일
  • 페이지마다 다른 쿼리 키가 필요하다 => 쿼리 키를 배열로 업데이트해서 가져오는 페이지 번호를 포함할 수 있게 하자
  • 사용자가 다음/이전 페이지 버튼을 누르면? => currentPage state를 업데이트 => 바뀐 쿼리 키를 감지해서 새로운 쿼리를 실행하게 된다
  • page api에서 1페이지부터 시작

= 쿼리 키에 currentPage 포함

  • 의존성 배열이 되었음
  • 쿼리 키가 바뀌면 함수도 실행되게 !


  • 현재 페이지가 1에 있거나, 1 이전에 있다면 // max보다 같거나 크다면 비활성화

  • onClick 함수에는 currentPage를 1씩 줄여줄/늘려줄 수 있게

  • 불편 사항 : 이전/다음 버튼을 누를 때 Loading이 걸린다

프리페칭

  • 데이터를 캐시에 추가하며 구성할 수 있지만, 기본적으로 만료(stale) 상태
  • 데이터를 사용하고자 할 때, 만료 상태에서 데이터를 가지고 온다
  • 데이터를 다시 가져오는 중에는 캐시에 있는 데이터를 이용해 앱에 나타냄
    => 캐시가 만료되지 않았다는 가정 하에
    => 만약 cacheTime 보다 페이지에 오래 머물다가 다음버튼을 누르면 캐시에 아무것도 남아있지 않기 때문에 loading이 나타날 것
  • 사용자가 추후에 사용할 법한 모든 데이터에 프리페칭을 사용해보자.
  • 예시
    • 페이지네이션
    • 웹 접속 후 누를 확률이 높은 특정 탭

사용하기

  • react-query에서 Import하고,

  • prefetch는 queryclient의 메서드 -> useQuery 훅을 통해 queryclient를 가져올 수 있다

  • 다음페이지 클릭 시에 실행하는 것은 적합하지 않는다
  • 상태 업데이트가 비동기 식으로 일어나기 때문에 이미 업데이트가 진행되었는지 알 방법이 없다.
    => 현재 페이지가 무엇인지 알 수 있는 방법이 없음
  • 대신 useEffect를 사용해서, 현재 페이지에 생기는 변경 사항을 적용

  • 현재 페이지가 최대 페이지보다 작을 때만 프리페칭을 진행할 것 (알고 있는 범위 외의 데이터 제외)
  • 의존성 배열에는 현재 페이지를 넣어 현재 페이지가 변경될 때마다 함수를 실행한다.
  • useEffect 안에서 실행할 함수는 queryClient.prefetchQuery
  • 쿼리 키는 useQuery와 같다. 단, 다음페이지를 불러오게 두 번째 인자를 넣어주고, fetchPosts의 인자도 다음페이지로
  • queryClient라는 의존성이 하나 더 생겨, 현재 페이지와 함께 추가.

  • useQuery에서는 쿼리키가 바뀔 때 지난 데이터를 유지하자.
    이전페이지로 돌아갔을 때 캐시에 해당 데이터가 남아있게.
  • keepPreviousData 속성을 추가한다.
    : 새 데이터가 요청되는 동안 마지막으로 가져온 성공 데이터를 화면에 유지

확인

데이터가 쌓여있다.
유일하게 활성상태인 것은 현재 페이지에 대한 쿼리
다음 페이지의 데이터를 미리 가져와 캐시에 둔다.

isFetching vs isLoading

isFetching

  • async 쿼리 함수가 해결되지 않았을 때 참에 해당

isLoding

  • isFetching이 참이면서 쿼리에 대해 캐시된 데이터가 없는 상태
  • isLoading 상태거나, 참인 경우 isFetching 또한 참
  • isLoading은 캐시된 데이터가 없고, 데이터를 가져오는 상황에 해당하는 isFetching의 부분집합

확인하기

  • 이 부분은 fetchPosts 함수가 실행 중이면서, 캐시된 데이터가 존재하지 않을 때 isLoading이 참이 된다.

  • 만약 이 부분을 isFetching으로 바꾸게 된다면, 캐시된 데이터의 존재 여부와 관계없이 이 로딩 인디케이터를 나타네게 된다. => 프리페치 전에 매번 나타나게 됨(nextPage 데이터를 포함한 캐시를 미리 가져오기도 전에)

  • 프리페치의 목적은 캐시된 데이터를 표시하면서 뒤에서는 데이터 업데이트 여부를 서버에게 조용히 확인하는 것이고, 만약 데이터가 업데이트 되었다면, 해당 데이터를 보여주는 것

프리페치의 작동방식 💬 잘 이해 안되었음 복습할 것!!

  • currentPage가 업데이트 될 때, 4페이지라면 => 캐시에 4페이지 데이터가 있는가 확인
  • 4페이지 데이터를 프리페치 했기 때문에 존재하지만, 자동으로 만료 상태가 적용됨 (0에서 변경하지 않았음)
  • fetchPosts를 실행하게 되고, 만약 다른 데이터를 반환하면 업데이트
  • 페이지에서도 새로운 데이터가 업데이트, 그 전에는 기존에 있던 것이 보이고 있었을 것
  • 다시 가져온 데이터가 캐시된 데이터와 동일한지 사용자는 알 수 없음
  • 데이터를 최신 상태로 유지하기 위해 서버와 확인한 것도 알 수 없음

뮤테이션

  • 서버에 데이터를 업데이트하도록 서버에 네트워크 호출을 실시함
  • ex) 블로그 작성, 삭제, 수정 등
  • 방법
    1) 서버 호출에서 모든 호출이 잘 진행될 것으로 간주하기. 아닐 경우 롤백 진행
    2) 변이 호출을 실행할 때 서버에서 받는 데이터를 취하고 업데이트 된 해당 데이터로 react-query 캐시 업데이트
    3) 관련 쿼리 무효화 -> 서버에서 리페치를 개시하여 클라이언트에 있는 데이터를 서버의 데이터와 최신 상태로 유지하게 함

useMutation

  • mutate 함수 반환
  • 우리가 변경사항을 토대로 서버를 호출할 때 사용할 것
  • 데이터를 저장하지 않음 -> 쿼리 키 필요 없음
  • isLoading은 존재하지만 isFetching은 성립하지 않음
  • 변이에 대한 캐시는 존재하지 않고, 재시도 또한 존재하지 않음 (useQuery 기본 3회, 설정은 가능)

삭제하기

useMutation import 하기

  • useQuery에 인수로서 전달하는 쿼리 함수와는 달리,
  • 우리가 인수로 전달하는 변이 함수의 경우 그 자체도 인수를 받을 수 있다.
  • 이 useMutation 에서 객체는 변이 함수를 반환하게 된다

  • 누군가 삭제 버튼을 클릭 할 때 이 변이 함수를 실행
  • 객체를 반환하는 deleteMutation 과 속성함수인 mutate를 실행
  • props에서 받은 postId가 무엇이든 상관없이 실행

  • postId는 props(post)에서 유래된 것이므로 post.id로만 써도 된다.
  • 이 컴포넌트에 대한 호출이 이루어질 때마다 변경되지는 않음
  • 인수를 제공할 수 있다는 점

  • 변이 함수를 호출할 때면 변이 속성에 인수 할당
  • 여기의 인수가 변이 함수의 인수가 되는 것

deleteMutation 반환 객체에서 사용할 수 있는 것들이 있다 => 호출 주기를 설정할 수 있다.

profile
반반무마니
post-custom-banner

0개의 댓글