nuxt logo

문서 번역(비공식)

useAsyncData

useAsyncData는 SSR 친화적인 컴포저블에서 비동기적으로 해결되는 데이터에 접근할 수 있게 해줍니다.

페이지, 컴포넌트, 플러그인 내에서 useAsyncData를 사용하여 비동기적으로 해결되는 데이터에 접근할 수 있습니다.

useAsyncDataNuxt 컨텍스트에서 직접 호출되도록 설계된 컴포저블입니다. 이는 반응형 컴포저블을 반환하고, 페이지가 하이드레이션될 때 클라이언트 측에서 데이터를 다시 가져오지 않고 서버에서 클라이언트로 Nuxt 페이로드에 응답을 추가하는 작업을 처리합니다.

사용법

pages/index.vue
const { data, status, error, refresh, clear } = await useAsyncData(
  'mountains',
  () => $fetch('https://api.nuxtjs.dev/mountains')
)

커스텀 useAsyncData 래퍼를 사용하는 경우, 컴포저블 내에서 이를 await하지 마세요. 이는 예기치 않은 동작을 유발할 수 있습니다. 커스텀 비동기 데이터 페처를 만드는 방법에 대한 자세한 내용은 이 레시피를 참조하세요.

data, status, error는 Vue ref이며 <script setup> 내에서 사용할 때 .value로 접근해야 합니다. 반면 refresh/executeclear는 일반 함수입니다.

Watch Params

내장된 watch 옵션은 변경 사항이 감지될 때 페처 함수를 자동으로 다시 실행할 수 있게 해줍니다.

pages/index.vue
const page = ref(1)
const { data: posts } = await useAsyncData(
  'posts',
  () => $fetch('https://fakeApi.com/posts', {
    params: {
      page: page.value
    }
  }), {
    watch: [page]
  }
)

Reactive Keys

계산된 ref, 일반 ref 또는 getter 함수를 키로 사용하여 키가 변경될 때 자동으로 업데이트되는 동적 데이터 페칭을 할 수 있습니다:

pages/[id\
const route = useRoute()
const userId = computed(() => `user-${route.params.id}`)

// 라우트가 변경되고 userId가 업데이트되면 데이터가 자동으로 다시 페칭됩니다
const { data: user } = useAsyncData(
  userId,
  () => fetchUserById(route.params.id)
)

useAsyncData는 컴파일러에 의해 변환되는 예약 함수 이름이므로, 자신의 함수를 useAsyncData로 명명하지 마세요.

이것도 참고 getting-started > data-fetching#useasyncdata

Params

  • key: 요청 간 데이터 페칭이 적절히 중복 제거될 수 있도록 보장하는 고유 키입니다. 키를 제공하지 않으면, useAsyncData 인스턴스의 파일 이름과 줄 번호에 고유한 키가 생성됩니다.
  • handler: 참 값을 반환해야 하는 비동기 함수입니다(예: undefined 또는 null이 아니어야 함). 그렇지 않으면 클라이언트 측에서 요청이 중복될 수 있습니다.

handler 함수는 SSR 및 CSR 하이드레이션 중 예측 가능한 동작을 보장하기 위해 부작용이 없어야 합니다. 부작용을 트리거해야 하는 경우, callOnce 유틸리티를 사용하세요.

  • options:
    • server: 서버에서 데이터를 페칭할지 여부 (기본값은 true)
    • lazy: 클라이언트 측 탐색을 차단하는 대신 라우트 로딩 후 비동기 함수를 해결할지 여부 (기본값은 false)
    • immediate: false로 설정하면 요청이 즉시 실행되지 않도록 방지합니다. (기본값은 true)
    • default: 비동기 함수가 해결되기 전에 data의 기본값을 설정하는 팩토리 함수 - lazy: true 또는 immediate: false 옵션과 유용하게 사용됩니다.
    • transform: 해결 후 handler 함수 결과를 변경하는 데 사용할 수 있는 함수
    • getCachedData: 캐시된 데이터를 반환하는 함수를 제공합니다. null 또는 undefined 반환 값은 페칭을 트리거합니다. 기본적으로 이는 다음과 같습니다:
      const getDefaultCachedData = (key, nuxtApp, ctx) => nuxtApp.isHydrating 
        ? nuxtApp.payload.data[key] 
        : nuxtApp.static.data[key]
      
      이는 nuxt.configexperimental.payloadExtraction이 활성화된 경우에만 데이터를 캐시합니다.
    • pick: handler 함수 결과에서 이 배열에 지정된 키만 선택
    • watch: 반응형 소스를 감시하여 자동 새로고침
    • deep: 깊은 ref 객체로 데이터를 반환 (true가 기본값). 데이터가 깊은 반응성을 필요로 하지 않는 경우 성능을 향상시키기 위해 false로 설정할 수 있습니다.
    • dedupe: 동일한 키를 한 번에 여러 번 페칭하지 않도록 방지 (기본값은 cancel). 가능한 옵션:
      • cancel - 새 요청이 있을 때 기존 요청을 취소
      • defer - 대기 중인 요청이 있는 경우 새 요청을 전혀 만들지 않음

내부적으로, lazy: false는 데이터를 페칭하기 전에 라우트 로딩을 차단하기 위해 <Suspense>를 사용합니다. 더 빠른 사용자 경험을 위해 lazy: true를 사용하고 로딩 상태를 구현하는 것을 고려하세요.

이것도 참고 api > composables > use-lazy-async-data

공유 상태 및 옵션 일관성

동일한 키로 여러 useAsyncData 호출을 사용하는 경우, 동일한 data, error, status ref를 공유합니다. 이는 컴포넌트 간의 일관성을 보장하지만 옵션 일관성이 필요합니다.

다음 옵션은 동일한 키로 모든 호출에서 일관성이 있어야 합니다:

  • handler 함수
  • deep 옵션
  • transform 함수
  • pick 배열
  • getCachedData 함수
  • default

다음 옵션은 경고 없이 다를 수 있습니다:

  • server
  • lazy
  • immediate
  • dedupe
  • watch
// ❌ 개발 경고가 발생합니다
const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })

// ✅ 허용됩니다
const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })

반환 값

  • data: 전달된 비동기 함수의 결과.
  • refresh/execute: handler 함수에 의해 반환된 데이터를 새로고침하는 데 사용할 수 있는 함수.
  • error: 데이터 페칭이 실패한 경우의 오류 객체.
  • status: 데이터 요청의 상태를 나타내는 문자열:
    • idle: 요청이 시작되지 않았을 때, 예를 들어:
      • execute가 아직 호출되지 않았고 { immediate: false }가 설정된 경우
      • 서버에서 HTML을 렌더링하고 { server: false }가 설정된 경우
    • pending: 요청이 진행 중
    • success: 요청이 성공적으로 완료됨
    • error: 요청이 실패함
  • clear: dataundefined로 설정하거나 (제공된 경우 options.default()의 값으로 설정), errornull로 설정하고, statusidle로 설정하며, 현재 대기 중인 요청을 취소된 것으로 표시하는 데 사용할 수 있는 함수.

기본적으로, Nuxt는 refresh가 완료될 때까지 다시 실행될 수 없습니다.

서버에서 데이터를 페칭하지 않은 경우(예: server: false), 하이드레이션이 완료될 때까지 데이터가 페칭되지 않습니다. 이는 클라이언트 측에서 useAsyncData를 await하더라도 <script setup> 내에서 datanull로 남아 있음을 의미합니다.

타입

Signature
function useAsyncData<DataT, DataE>(
  handler: (nuxtApp?: NuxtApp) => Promise<DataT>,
  options?: AsyncDataOptions<DataT>
): AsyncData<DataT, DataE>
function useAsyncData<DataT, DataE>(
  key: string | Ref<string> | ComputedRef<string>,
  handler: (nuxtApp?: NuxtApp) => Promise<DataT>,
  options?: AsyncDataOptions<DataT>
): Promise<AsyncData<DataT, DataE>>

type AsyncDataOptions<DataT> = {
  server?: boolean
  lazy?: boolean
  immediate?: boolean
  deep?: boolean
  dedupe?: 'cancel' | 'defer'
  default?: () => DataT | Ref<DataT> | null
  transform?: (input: DataT) => DataT | Promise<DataT>
  pick?: string[]
  watch?: WatchSource[] | false
  getCachedData?: (key: string, nuxtApp: NuxtApp, ctx: AsyncDataRequestContext) => DataT | undefined
}

type AsyncDataRequestContext = {
  /** 이 데이터 요청의 이유 */
  cause: 'initial' | 'refresh:manual' | 'refresh:hook' | 'watch'
}

type AsyncData<DataT, ErrorT> = {
  data: Ref<DataT | null>
  refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
  execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
  clear: () => void
  error: Ref<ErrorT | null>
  status: Ref<AsyncDataRequestStatus>
};

interface AsyncDataExecuteOptions {
  dedupe?: 'cancel' | 'defer'
}

type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
이것도 참고 getting-started > data-fetching