[React-query] mutate와 useMutation

H_Chang·2023년 12월 20일
1

useMutation이란?

  • useMutation은 useQuery로 정의한 데이터를 update,delete해주는 리액트 쿼리 훅입니다.

useMutation 사용법

  • 기본적으로 useQuery와 비슷하지만 query key가 안들어 간다는 차이점이 있습니다.
const { data, isLoading, mutate, mutateAsync } = useMutation(mutationFn, options);

첫번째 인자에는 업데이트 될때 반응 할 비동기함수가 들어가며
두번째 인자에는 옵션이 들어간다.

useMutation에서 가장 많이 쓰는 3가지 옵션이 있습니다.
1. optimistic update
2. invalidateQueries
3. setQueryData

optimistic update (낙관적 업데이트)

  • 사용자에게 바로바로 보여야하는 간단한 서버요청이 있다.
  • 하지만 데이터응답을 받을떄까지 약간의 딜레이가 있는데 그 딜레이를 없애기위해
    더미로 만든 성공한 데이터를 응답을 받기전에 미리 사용자에게 보여주는것을 낙관적 업데이트라고 한다.

invalidateQueries

  • invalidateQueries는 useQuery에서 사용되는 queryKey의 캐시 데이터를 제거한다.
  • 그렇게 되면 캐시가 없기떄문에 staleTiem,cashTime을 무시하고 무조건 새로운 데이터를 가져올 수 있게 된다.
 const updateMutation = useMutation(() => updatePost(post.id),{
 onSuccess: () => { // 요청이 성공한 경우
        console.log('onSuccess');
        queryClient.invalidateQueries('getCommnet'); // queryKey 유효성 제거
    },
 });

setQueryData

  • invalidateQueries는 해당 queryKey의 캐시를 제거해서 새로운 데이터를 가져오는 반면,
  • setQueryData는 queryKey를 제거하지않지만 그냥 바로 새로운 데이터를 fetching 해온다.

useMutation의 설정 (공식문서)

// useMutation
const {
 data,
 error,
 isError,
 isIdle,
 isLoading,
 isPaused,
 isSuccess,
 mutate,
 mutateAsync,
 reset,
 status,
} = useMutation(mutationFn, {
 cacheTime,
 mutationKey,
 networkMode,
 onError,    // onError는 에러가 발생될 경우 실행되는 구간입니다.
 onMutate,
 onSettled, // onSettled는 finally 구문처럼 요청이 성공하든 에러가 발생되든 상관없이 마지막에 실행되는 구간입니다.
 onSuccess, // onSuccess는 요청이 성공되었을 때 실행되는 구간입니다.
 retry,
 retryDelay,
 useErrorBoundary,
 meta
})

// mutate함수
mutate(variables, {
 onError,
 onSettled,
 onSuccess,
})

mutate란?

 const deleteMutation = useMutation((postId) => deletePost(postId));

  <button
        onClick={() => {
          deleteMutation.mutate(post.id);
        }}
      >
  • useMutation을 선언한 deleteMutation안에 mutate라는 속성이 있다.
  • mutate는 useMutation을 조작할 수 있는 속성입니다 mutate안에는 useMutation의 비동기 함수에 들어갈 인자가 들어간다.

밑에 예시를 보고 어떤건지 살펴보자

import { useMutation, useQuery } from "@tanstack/react-query";

async function fetchComments(postId) {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/comments?postId=${postId}`
  );
  return response.json();
}

async function deletePost(postId) {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/postId/${postId}`,
    { method: "DELETE" }
  );
  return response.json();
}

async function updatePost(postId) {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/postId/${postId}`,
    { method: "PATCH", data: { title: "REACT QUERY FOREVER!!!!" } }
  );
  return response.json();
}

export function PostDetail({ post }) {
  // replace with useQuery
  const { data, isLoading, isError } = useQuery(["getCommnet", post.id], () =>
    fetchComments(post.id)
  );
  const deleteMutation = useMutation((postId) => deletePost(postId)); //인수전달가능
  const updateMutation = useMutation(() => updatePost(post.id));
  if (isError) {
    return "An error occurred";
  }

  return (
    <>
      {updateMutation.isLoading ? <p>updating data</p> : ""}
      {updateMutation.isSuccess ? <p>update finish!</p> : ""}
      {updateMutation.isError ? <p>updateError data</p> : ""}
      <h3 style={{ color: "blue" }}>{post.title}</h3>
      <button
        onClick={() => {
          deleteMutation.mutate(post.id);
        }}
      >
        Delete
      </button>
      {deleteMutation.isError && <p>Error deleting the post</p>}
      {deleteMutation.isLoading && <p>deleting the post</p>}
      {deleteMutation.isSuccess && <p>Post has been deleted</p>}
      <button onClick={() => updateMutation.mutate(post.id)}>
        Update title
      </button>
      <p>{post.body}</p>
      <h4>Comments</h4>
      {isLoading ? (
        <div>로딩중입니다...</div>
      ) : (
        data?.map((comment) => (
          <li key={comment.id}>
            {comment.email}: {comment.body}
          </li>
        ))
      )}
    </>
  );
}
profile
프론트 엔드 시작하는 뉴비!

0개의 댓글