너 아직도 refetch 쓰니?

김석진·2023년 2월 23일
9
post-thumbnail
post-custom-banner

refetch란?

refetch란 쉽게 말하면 post 혹은 delete 요청을 하면 화면에 보여주는 데이터도
업데이트를 해줘야 한다 그러나 사용자가 새로고침 혹은 화면을 나갔다 들어오는 행동을 하지 않으면 업데이트가 되지 않는다 이럴 때 우리는 refetch를 사용했다

사건의 결말

하지만 문제가 있었는데...

내가 개발하던 페이지에는 상세 페이지, 댓글, 동의하기 컴포넌트가 있었고
상세페이지가 부모 댓글, 동의하기가 자식이었다 그래서

사용자가 댓글을 썼을 때 데이터 최신화를 해주지 않으면
화면상 데이터가 업데이트되지 않았다

학생 청원 상세페이지의 구조는 상세페이지가 get으로 데이터를 뿌려주고 있었기에
댓글을 쓰고 데이터 최신화를 하려면 상세페이지에서 props로 댓글 쓰기 컴포넌트에 refetch를 보내줘야 하는 상황이었다

하지만 나는 별로 좋은 방법이라 생각하지 않았고 다른 방법이 없을까 찾던 도중
새로운 방법을 찾았다

Query Invalidation

Query Invalidation는 캐싱 키를 사용하여 어디서든 refetch를 할 수 있는 것이었다

import { useQueryClient } from 'react-query';

const queryClient = useQueryClient();

queryClient.invalidateQueries(['datas']);

이렇게 하면 refetch를 props로 넘기지 않아도 되어 나의 문제를 해결할 수 있었다

자세한 사용법

우선 제가 직접 적용한 코드를 예시로 설명을 하겠습니다

detail.feature.ts

import { getPetitionDetail } from 'apis/petition.api';
import { useQuery } from 'react-query';
import { PetitionDetailType } from 'types/petition.type';
import * as KEY from 'constants/key.constant';

export const DetailFeature = (petitionId: number) => {
  const { isLoading, isError, data } = useQuery<PetitionDetailType>(
    [KEY.PETITION, petitionId],
    () => getPetitionDetail(petitionId),
  );

  return {
    isLoading,
    isError,
    data
  };
};

쿼리의 키는 KEY.PETITION이고 나는 지금 위에서 설명했던 것과 같이 쿼리 키를 이용해 자식 컴포넌트에서 이벤트가 발생하였을 때 detail.feature에 data를 최신화해주고 싶다 그렇게 할 때 우리는 Query Invalidation 써주면 된다

import { commentPetition } from 'apis/petition.api';
import { useMutation, useQueryClient } from 'react-query';
import { Dispatch, SetStateAction } from 'react';
import * as KEY from 'constants/key.constant';
import { useErrorToast } from 'hooks/useToast';

interface CommentFeatureType {
  petitionId: number;
  setComment: Dispatch<SetStateAction<string>>;
  comment: string;
}

export const CommentFeature = ({
  petitionId,
  setComment,
  comment,
}: CommentFeatureType) => {
  const queryClient = useQueryClient();

  const commentMutate = useMutation(commentPetition, {
    onSuccess: () => {
      setComment('');
      queryClient.invalidateQueries([KEY.PETITION]);
    },
    onError: (err) => {
      console.log(err);
      useErrorToast('크기가 2에서 500 사이여야 합니다');
    },
  });

  const commentSubmit = () => {
    commentMutate.mutate({
      comment,
      petitionId,
    });
  };

  return { commentSubmit };
};

이런 식으로 Query Invalidation를 사용하여 최신화를 하면 된다
이렇게 하면 댓글을 썼을 때 최신 화가 되어 사용자 화면에서 바로 업데이트가 된다!
정말 간단하죠??

앞으로 나와 같은 상황일 때는 Query Invalidation 써서 효율적으로 코딩하자!

잘못된 내용이 있으면 언제든지 지적해 주세요

참고 한 자료

https://tanstack.com/query/v4/docs/react/guides/query-invalidation

profile
해탈의 경지에 이르자
post-custom-banner

2개의 댓글

comment-user-thumbnail
2023년 2월 23일

유용해요!

답글 달기
comment-user-thumbnail
2023년 2월 23일

저도 같은 문제가 있었는데 이런게있군요 ㄷㄷ 굿 감사합니다~

답글 달기