[React Query] Mutation

먼지·2023년 9월 18일
0

React Query

목록 보기
4/4
post-thumbnail

React Query는 fetching, caching, 서버 데이터와 동기화 등의 기능을 지원해주는 라이브러리로, 서버로부터 데이터를 가져오거나 변경하는 등 다양한 작업을 쉽게 할 수 있도록 도와줍니다ㅏ. 가장 큰 장점인 캐싱은 반복적인 비동기 데이터 호출을 방지하고 서버 부하를 줄입니다.

Qeury

쿼리는 서버로부터 데이터를 읽어오는 GET 요청 작업을 실행할 때 사용합니다

import { useQuery } from '@tanstack/react-query'

function Todos() {
  const query = useQuery({ queryKey: ['todos'], queryFn: getTodos })

  return (
    <ul>
      {query.data?.map((todo) => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

Mutation

쿼리와 달리 뮤테이션은 일반적으로 서버 상태를 변경하는 작업인 데이터를 생성/업데이트/삭제하거나 서버의 사이드 이펙트(side effect, 예상치 못한 부수 효과로 의도치 않은 결과)를 수행할 때 사용합니다. 이를 위해 useMutation 훅을 사용합니다. 여러 가지 콜백 함수 옵션(onMutate, onError 등)과 함께 사용해 다양한 경우에 대응할 수 있습니다

import { useMutation } from '@tanstack/react-query'

function Todos() {
  const mutation = useMutation({
    mutationFn: postTodo,
    onMutate: () => {
      // 뮤테이션이 발생하기 직전에 호출됨. 옵티미스틱 업데이트 작업 등
    },
    onError: () => {
      // 뮤테이션이 실패하면 호출됨. 에러 처리 로직 작성
    },
    onSuccess: () => {
      // 뮤테이션이 성공적으로 완료된 후 호출됨
      // Invalidate and refetch
      queryClient.invalidateQueries({ queryKey: ['todos'] })
    },
    onSettled: () => {
      // 성공, 실패 여부와 관계없이 요청 후 마지막에 실행됨
      // 클린업 작업이나 쿼리 무효화 등
    }
  })
  
  return (
    <button
      onClick={() => {
        mutation.mutate({
          id: Date.now(),
          title: 'Do Laundry',
        })
      }}
    >
      Add Todo
    </button>
  );
}

Optimistic Update

옵티미스틱 업데이트는 서버 응답을 기다리지 않고 즉시 UI를 업데이트하는 방식으로 사용자에게 좋은 경험을 제공할 수 있습니다. 서버 응답이 실패할 경우 롤백(원상태로 되돌리기) 로직을 포함해야 UI와 실제 데이터 상태가 유지될 수 있습니다. useMutaion 훅의 onMutate 콜백 함수에서 구현할 수 있습니다.

function Todos() {
  const queryClient = useQueryClient()
  ...
  const mutation = useMutation({
    mutationFn: postTodo,
    onMutate: async (newTodo) => {
      const previousTodos = queryClient.getQueryData('todos');

      // 즉시 새로운 todo를 추가하여 UI 업데이트
      queryClient.setQueryData('todos', old => [...old, newTodo]);

      return { previousTodos };
    },
    onError: (err, newTodo, context) => {
      // 실패 시 롤백 수행
      queryClient.setQueryData('todos', context.previousTodos);
    },
    ...
  })
    
  return ();
}
profile
꾸준히 자유롭게 즐겁게

0개의 댓글