react-query v4 공식문서 : Query Cancellation

👾·2022년 8월 12일
0

react-query

목록 보기
23/27
post-thumbnail

공식문서 : https://tanstack.com/query/v4/docs/guides/query-cancellation

Query Cancellation

React Query는 런타임 환경에서 사용가능한 경우 AbortSignal 인스턴스와 함께 각 쿼리 함수를 제공한다. 쿼리가 오래되거나 inactive 되면, signal이 abort가 된다. 즉, 모든 쿼리를 취소할 수 있으며 원하는 경우 쿼리 함수 내에서 취소에 응답할 수 있다. 이것의 가장 좋은 점은 자동 취소의 이점을 모두 얻으면서도 일반 async/await 구문을 계속 사용할 수 있다는 것이다. 또한, 이 솔루션은 이전 솔루션보다 Typescript에서 더 잘 작동한다.

AbortController API는 대부분의 런타임 환경에서 사용할 수 있지만, 런타임 환경에서 지원하지 않는 경우 쿼리함수가 undefined을 대신 수신한다. 원하는 경우 AbortController API를 폴리필(웹브라우저상에서 지원하지 않는 기능을 구현)할 수 있고, 이용가능한 여러가지가 있다.

Default behavior

기본적으로 promise들이 resolve되기 전에 unmount되거나 사용되지 않게 된 쿼리는 취소되지 않는다. 즉, promise가 resolve된 후 결과 데이터를 캐시에서 사용할 수 있음을 의미한다. 이는 쿼리를 수신하기 시작했지만 완료되기 전에 컴포넌트를 unmount한 경우 유용하다. 컴포넌트를 다시 mount하고 쿼리가 아직 garbage collect되지 않은 경우에는, 데이터를 사용할 수 있다.

그러나, AbortSignal을 사용하거나 cancel 함수를 Promise에 부착하면, Promise가 취소되므로(예: fetch 중단), Query도 취소되어야한다. 쿼리를 취소하면 해당 state가 이전 state로 돌아간다.

Using fetch

const query = useQuery(['todos'], async ({ signal }) => {
  const todosResponse = await fetch('/todos', {
    // Pass the signal to one fetch
    signal,
  })
  const todos = await todosResponse.json()

  const todoDetails = todos.map(async ({ details } => {
    const response = await fetch(details, {
      // Or pass it to several
      signal,
    })
    return response.json()
  })

  return Promise.all(todoDetails)
})

Using axios v0.22.0+

import axios from 'axios'

const query = useQuery(['todos'], ({ signal }) =>
  axios.get('/todos', {
    // Pass the signal to `axios`
    signal,
  })
)

Using XMLHttpRequest

const query = useQuery(['todos'], ({ signal }) => {
  return new Promise((resolve, reject) => {
    var oReq = new XMLHttpRequest()
    oReq.addEventListener('load', () => {
      resolve(JSON.parse(oReq.responseText))
    })
    signal?.addEventListener('abort', () => {
      oReq.abort()
      reject()
    })
    oReq.open('GET', '/todos')
    oReq.send()
  })
})

Manual Cancellation

쿼리를 수동으로 취소할 수 있다. 예를들어, 요청을 완료하는데 오랜 시간이 걸리는 경우 유저가 취소 버튼을 클릭하여 요청을 중지할 수 있게 할 수 있다. 이렇게 하려면 쿼리를 취소하고 이전 상태로 되돌리는 queryClient.cancelQueries(key)를 호출하기만 하면 된다. promise.cancel을 사용할 수 있거나 쿼리 함수에 전달된 signal를 사용했다면, React Query는 Promise도 추가로 취소한다.

const query = useQuery(['todos'], async ({ signal }) => {
  const resp = await fetch('/todos', { signal })
  return resp.json()
})

const queryClient = useQueryClient()

return (
  <button onClick={(e) => {
    e.preventDefault()
    queryClient.cancelQueries(['todos'])
   }}>Cancel</button>
)

0개의 댓글