리액트 쿼리 기초

LEE GYUHO·2024년 1월 16일
0

Status

  • Query Status: query status는 세 가지 상태값을 가진다.
    • pending: 아직 데이터를 받아오지 못했을 때
    • success: 데이터를 성공적으로 받아올 때
    • error: 데이터를 받아오는 중 에러가 발생했을 때
  • Fetch Status: fetch status는 세 가지 상태 값을 가진다.
    • fetching: 현재 쿼리 함수(queryFn)가 실행되고 있는 중일 때
    • paused: 쿼리 함수가 시작은 했는데 실제로 실행되고 있지 않을 때
    • idle: 쿼리 함수가 어떤 작업도 하고 있지 않는 상황(fetching 상태도 아니고 paused 상태도 아닌 경우)

캐시

  • queryKey로 캐시에 저장되어 있는 것을 확인할 수 있다.

  • useQuery()는 쿼리 키로 캐시에 저장된 데이터가 있는지 확인 후 저장된 데이터가 없으면 쿼리 함수를 실행하여 데이터를 받아온 후 쿼리 키로 데이터를 캐시에 저장한다.

  • 저장된 데이터가 있다면 그 데이터를 리턴한다.

    • 데이터가 fresh 상태라면 캐시에 저장된 데이터 리턴.
    • 데이터가 stale 상태라면 백그라운드에서 refetch를 진행. 그리고 캐시되어 있던 데이터 갱신
    • refetch 옵션
      • refetchOnMount: 새로운 쿼리 인스턴스가 마운트될 때
      • refetchOnWindowFocus: 브라우저 창에 다시 포커스가 갈 때
      • refetchOnReconnect: 네트워크가 다시 연결될 때
      • refetchInterval: 미리 설정해 둔 refetch interval 시간이 지났을 때
  • Stale Time

    • 디폴트 값은 0이다.
  • Garbage Collection Time

    • 쿼리 컴포넌트가 언마운트 되어 해당 데이터가 쓰이지 않는 상황이 되면 inactive 상태가 된다. 그리고 garbage collection time이 지나면 캐시에서 삭제된다.
    • 디폴트 값은 5분이다.
  • 라이프 사이클

  • 특정 데이터만 따로 저장

function HomePage() {
  const username = 'codeit'; // 임의로 username을 지정
  const { data: postsDataByUsername } = useQuery({
    queryKey: ['posts', username],
    queryFn: () => getPostsByUsername(username),
  });
  console.log(postsDataByUsername);
  
  return <div>홈페이지</div>;
}

로딩과 에러 처리 옵션

  • isPending, isError
function HomePage() {
  const {
    data: postsData,
    isPending,
    isError,
  } = useQuery({
    queryKey: ['posts'],
    queryFn: getPosts,
    retry: 0,
  });

  if (isPending) return '로딩 중입니다...';

  if (isError) return '에러가 발생했습니다.';

  const posts = postsData?.results ?? [];

  return (
    <div>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>
            {post.user.name}: {post.content}
          </li>
        ))}
      </ul>
    </div>
  );
}
  • 리액트 쿼리에서 에러가 발생하면 기본적으로 재시도 3번을 한다.
    • 이 옵션을 수정하고 싶으면 retry 횟수를 조정하면 된다.
function HomePage() {
  const {
    data: postsData,
    isPending,
    isError,
  } = useQuery({
    queryKey: ['posts'],
    queryFn: getPosts,
    retry: 0,
  });

useMutation

  • useMutation()과 useQuery()의 차이점

    • useQuery()의 쿼리 함수는 컴포넌트가 마운트되면서 자동으로 실행되지만, useMutation()은 실제로 뮤테이션하는 함수를 직접 실행해 줘야 한다.
    • mutate() 함수를 통해 mutationFn으로 등록했던 함수를 실행할 수 있고, 그래야만 백엔드 데이터를 실제로 수정할 수 있다.
  • useMutation() 훅을 이용해 새로운 데이터를 추가해도 캐시에 있는 데이터가 업데이트 되지 않기 때문에 자동으로 refetch 시켜주는 invalidateQueries()를 사용해줘야 한다.

    • 쿼리를 invalidate하면 해당 쿼리를 통해 받아 온 데이터를 stale time이 지났는지 아닌지에 상관없이 무조건 stale 상태로 만들고, 해당 데이터를 백그라운드에서 refetch하게 된다.
    • 뮤테이션이 성공한 시점에 쿼리를 invalidate 해주는 함수를 콜백으로 등록
    import { useQueryClient } from '@tanstack/react-query'
    
     const queryClient = useQueryClient();
    
     // ...
    
     queryClient.invalidateQueries();

    
    const queryClient = useQueryClient();
    
    // ...
    
    const uploadPostMutation = useMutation({
      mutationFn: (newPost) => uploadPost(newPost),
      onSuccess: () => {
        queryClient.invalidateQueries({ queryKey: ['posts'] });
      },
    });
    
  • useMutation() 함수의 콜백 옵션

    • onMutate
    • onSuccess
    • onError
    • onSettled
  • mutate() 함수의 콜백 옵션

    • onMutate
    • onSuccess
    • onError
    • onSettled
  • useMutation()에 등록된 콜백이 먼저 실행 그 후 mutate()에 등록한 콜백 함수 실행

    • useMutation()에 등록된 콜백 함수들은 컴포넌트가 언마운트되더라도 실행이 되지만, mutate()의 콜백 함수들은 만약 뮤테이션이 끝나기 전에 해당 컴포넌트가 언마운트되면 실행되지 않는다.
profile
누구나 같은 팀으로 되길 바라는 개발자가 되자

0개의 댓글