🔥 쿼리 비활성화 및 일시 중지
쿼리가 자동으로 실행되는 것을 막고 싶을 때가 있습니다. 이런 경우 enabled = false
옵션을 사용할 수 있습니다. enabled
옵션은 불리언 값을 반환하는 콜백 함수도 받을 수 있습니다.
enabled
가 false
일 때 다음과 같은 상황이 발생합니다:
- 쿼리에 캐시된 데이터가 있다면,
status === 'success'
또는isSuccess
상태로 초기화됩니다. - 쿼리에 캐시된 데이터가 없다면,
status === 'pending'
과fetchStatus === 'idle'
상태로 시작합니다. - 쿼리는 마운트 시 자동으로 데이터를 가져오지 않습니다.
- 쿼리는 백그라운드에서 자동으로 데이터를 다시 가져오지 않습니다.
- 쿼리는 쿼리 클라이언트의
invalidateQueries
와refetchQueries
호출을 무시합니다. 이 호출은 보통 쿼리가 데이터를 다시 가져오게 만듭니다. useQuery
가 반환하는refetch
함수를 사용해 수동으로 쿼리 실행을 트리거할 수 있습니다. 하지만skipToken
과 함께 사용할 수는 없습니다.
TypeScript 사용자라면 enabled = false 대신 skipToken을 사용하는 것이 좋습니다.
function Todos() { const { isLoading, isError, data, error, refetch, isFetching } = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList, enabled: false, }) return ( <div> <button onClick={() => refetch()}>할 일 목록 가져오기</button> {data ? ( <> <ul> {data.map((todo) => ( <li key={todo.id}>{todo.title}</li> ))} </ul> </> ) : isError ? ( <span>오류: {error.message}</span> ) : isLoading ? ( <span>로딩 중...</span> ) : ( <span>준비되지 않음 ...</span> )} <div>{isFetching ? '데이터 가져오는 중...' : null}</div> </div> ) }
typescript
쿼리를 영구적으로 비활성화하면 TanStack Query가 제공하는 많은 좋은 기능(예: 백그라운드 리페치)을 사용할 수 없게 됩니다. 또한 이는 TanStack Query의 선언적 접근 방식(쿼리가 실행되어야 할 때의 의존성 정의)에서 벗어나 명령적 모드(여기를 클릭할 때마다 가져오기)로 전환됩니다. refetch
에 매개변수를 전달할 수도 없습니다. 대부분의 경우, 여러분이 원하는 것은 초기 데이터 가져오기를 지연시키는 지연 쿼리일 것입니다.
지연 쿼리
enabled
옵션은 쿼리를 영구적으로 비활성화하는 데만 사용되는 것이 아니라, 나중에 쿼리를 활성화하거나 비활성화하는 데도 사용할 수 있습니다. 좋은 예로 필터 폼이 있습니다. 사용자가 필터 값을 입력한 후에만 첫 번째 요청을 보내고 싶을 때 이 옵션을 사용할 수 있습니다:
function Todos() { const [filter, setFilter] = React.useState('') const { data } = useQuery({ queryKey: ['todos', filter], queryFn: () => fetchTodos(filter), // ⬇️ 필터가 비어있는 동안 비활성화됨 enabled: !!filter, }) return ( <div> {/* 🚀 필터를 적용하면 쿼리가 활성화되고 실행됨 */} <FiltersForm onApply={setFilter} /> {data && <TodosTable data={data} />} </div> ) }
typescript
isLoading (이전의 isInitialLoading)
지연 쿼리는 처음부터 status: 'pending'
상태입니다. 왜냐하면 'pending'은 아직 데이터가 없다는 것을 의미하기 때문입니다. 이는 기술적으로 사실이지만, 쿼리가 활성화되지 않았기 때문에 현재 데이터를 가져오고 있지 않습니다. 따라서 이 플래그를 로딩 스피너를 표시하는 데 사용하기 어려울 수 있습니다.
비활성화되거나 지연된 쿼리를 사용하고 있다면, isLoading
플래그를 대신 사용할 수 있습니다. 이는 다음과 같이 계산된 플래그입니다:
isPending && isFetching
따라서 쿼리가 처음으로 데이터를 가져오고 있을 때만 true
가 됩니다.
skipToken을 사용한 타입 안전한 쿼리 비활성화
TypeScript를 사용한다면 쿼리를 비활성화하기 위해 skipToken
을 사용할 수 있습니다. 이는 조건에 따라 쿼리를 비활성화하면서도 타입 안전성을 유지하고 싶을 때 유용합니다.
중요: useQuery에서 반환된 refetch는 skipToken과 함께 작동하지 않습니다. 그 외에는 skipToken은 enabled: false와 동일하게 작동합니다.
function Todos() { const [filter, setFilter] = React.useState<string | undefined>() const { data } = useQuery({ queryKey: ['todos', filter], // ⬇️ 필터가 undefined이거나 비어있는 동안 비활성화됨 queryFn: filter ? () => fetchTodos(filter) : skipToken, }) return ( <div> {/* 🚀 필터를 적용하면 쿼리가 활성화되고 실행됨 */} <FiltersForm onApply={setFilter} /> {data && <TodosTable data={data} />} </div> ) }
typescript
이 방식을 사용하면 쿼리의 활성화 여부를 타입 시스템을 통해 안전하게 제어할 수 있으며, 동시에 코드의 가독성과 유지보수성을 높일 수 있습니다.