패스트캠퍼스 데브캠프 69~73일차 [React, TanStackQuery]

Su Min·2024년 9월 2일
0
post-thumbnail

🔗 TanStack Query

TanStack Query는 서버에서 받은 데이터의 상태관리와 캐시 처리를 보다 간편하게 할 수 있는 비동기 상태 관리 라이브러리이다.

TanStack Query는 데이터 캐싱을 통해 불필요한 네트워크 요청을 방지하고 success, loading, error의 상태를 바로 얻어 비동기 상태를 구분하기 위해 필요한 코드를 줄일 수 있다

// main.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

const queryClient = new QueryClient() 

createRoot(document.getElementById('root')!).render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>
)

QueryClientProvider를 통해 생성자 함수를 호출하는 인스턴스 queryClient를 props로 전달해주면 하위 컴포넌트에서 QueryClient에 접근 할 수 있다.

🔗 useQuery

useQuery는 서버에서 데이터를 가져올 때(GET, POST포함) 사용된다.

// app.tsx
const { data, isLoading, isError } = useQuery<return되는data타입>({
  queryKey: ['data', 'read'],
  queryFn: async () => {
    const res = await fetch('서버주소', { 요청 할 내용 })
    const data = await res.json()
    return data
  },
  // option ...
})

url이 동적 파라미터인 경우엔 함수를 생성하여 내부에 useQuery를 작성하고 parameter를 받아 동적으로 데이터를 받을 수 있도록 한다.

const useFetchData = (id: string) => {
  return useQuery<return되는data타입>({
    queryKey: ['data', id ],
    queryFn: async () => {
      const res = await fetch(`https://example.com/data/${id}`)
      const data = await res.json()
      return data
    }
    // option ...
}
const { data, error } = useFetchData(id)

useQuery Options

  • 필수옵션인 queryKey는 고유한 쿼리 키(식별자)로 만약 두개의 useQuery가 각 옵션과 옵션의 내용이 달라도 queryKey가 같다면 같은 useQuery로 인식이 된다. 쿼리키만 같은 두개의 useQuery가 있을 때 두번째 쿼리는 첫번째쿼리의 캐시된 데이터를 반환하게 되어 queryKey는 비교가 가능하도록 고유한 키로 작성하여야 한다.

  • 필수옵션인 queryFn는 데이터를 가져오는 쿼리함수로 데이터나 오류를 반환한다.

  • enabled는 쿼리 자동 실행 여부로 기본값은 true이기때문에 useQuery가 마운트되면 바로 실행되며 false이면 초기 마운트 시에는 실행되지 않는다.

  • initialData는 쿼리함수에서 반환되는 data가 있기 전에(=쿼리가 생성되기 전에) 초기데이터를 지정할 수 있다.

  • retry는 쿼리 실패시 재시도 횟수를 지정할 수 있는 옵션이다.

  • select는 쿼리함수에서 반환되는 데이터 중에서 데이터를 선택하여 가져올 함수로 queryFn에서 반환되는 data 중에서 선택된 data를 반환한다.

  • staleTime는 데이터를 캐싱할 필요가 있을 시 데이터가 상하는데에 걸리는 시간을 정하여 데이터를 캐싱한다. 예를들어 매요청마다 데이터(ex.시간)가 달라질 경우에 사용할 수 있다.

useQuery 반환 속성

  • data 성공적으로 가져온 데이터

  • refetch 캐시된 데이터가 있다면 무시하고 데이터를 새로 다시 가져오는 함수이다.

  • isLoading 쿼리함수가 진행중 일 때 반환되는 boolean값으로 쿼리의 첫번째 가져오기가 진행 중인 경우를 나타내며 최초 한 번 동작한다. 스켈레톤UI를 보여줄 때 유용한 속성이다.

  • isFetching 쿼리함수가 실행 중의 여부로 초기 useQuery가 실행 될 때와 refetch시에 가져오는 중임을 나타낸다. 즉, 서버와 통신할 때 마다 실행된다.

  • error 오류 발생시 반환되는 객체이다.

  • isError 쿼리 함수에서의 오류 발생을 나타낸다.

🔗 useMutation

데이터 변경 작업을 위한 useMutation 훅은 생성, 수정, 삭제 등의 변이 작업을 처리하고 요청상태 및 결과를 제공한다. (POST, PUT, DELETE)

useMutation Options

  • 필수옵션인 mutationFn 은 변이를 실행하는 함수이다. mutate가 호출 될때마다 실행되며 useQuery의 queryFn과 비슷한 역할을 하지만 자동으로 요청을 보내는 것이 아닌 mutate를 호출할 때만 서버에 요청을 보낸다.

  • onMutate mutationFn과 동시에 실행되는 함수로 비동기 로직이 끝날때까지 기다리지 않고 UI에 바뀐 데이터로 낙관적 업데이트를 해준다.

  • onSuccess mutation이 성공적으로 완료되면 호출되는 함수로 mutate가 반환하는 데이터와 mutation을 실행할 때 전달된 인자를 참조하여 variables로 받는다. 서버요청이 완료 된 이후 실행되기때문에 최적화를 위해 onMutate를 활용하는 것이 더 좋다.

  • onError mutation에서 오류가 발생하면 실행되는 함수로 mutate가 반환하는 데이터와 에러, context를 인자로 받는다. context는 낙관적 업데이트를 했을 시 사용했던 캐시된 객체 데이터이며 낙관적 업데이트 된 데이터를 복원 할 수 있다.

  • onSettled mutation이 성공, 실패에 상관없이 실행이 완료되면 항상 호출되는 함수이다.

export function useCreateData() {
  const queryClient = useQueryClient() 

  return useMutation({
    mutationFn: async (newData) => {
      const res = await fetch('...', { ... })
      const data = await res.json()
      return data
    },
    onMutate: async (newData) => {
      // 낙관적 업데이트
      const id = newData.id
      const previousData = queryClient.getQueryData(['data', id ]) 
      if(previousData) {
        queryClient.setQueryData(['data', id ],[...previousData, newData])
      }
      return { previousData }
    },
    onSuccess: (_newData, variables) => {
      const id = variables.id
      queryClient.invalidateQueries({ queryKey: ['data', id ] })
    },
    onError: (_error, newData, context) => {
      const id = newData.id
      if (context?.previousData) {
        queryClient.setQueryData(['data', id ], context.previousData)
      }
    },
  })
}

const { mutate: mutateForCreate } = useCreateData()

queryClient

QueryClientProvider의 props인 queryClient를 useQueryClient()훅을 통해 사용 할 수 있다. queryClient에는 캐싱된 데이터와 위의 코드에서 사용된 getQueryData, setQueryData, invalidateQueries 등 다양한 메서드가 들어있다.

  • getQueryData( ) 인자로 queryKey를 받아 캐시된 데이터를 반환한다.

  • setQueryData( ) 인자로 queryKey와 새로운데이터를 받아 캐시된 데이터에 새로운 데이터를 넣는다.

  • invalidateQueries( ) mutation이 성공 이후 기존 캐시된 데이터 쿼리를 무효화(invalidate)하여 새로 캐싱한다.

profile
성장하는 과정에서 성취감을 통해 희열을 느낍니다⚡️

0개의 댓글

관련 채용 정보