nuxt logo

ドキュメント翻訳(非公式)

useAsyncData

useAsyncDataは、SSRに適したコンポーザブルで非同期に解決されるデータへのアクセスを提供します。

ページ、コンポーネント、プラグイン内で、useAsyncDataを使用して非同期に解決されるデータにアクセスできます。

useAsyncDataは、Nuxtコンテキストで直接呼び出すことを意図したコンポーザブルです。これはリアクティブなコンポーザブルを返し、ページがハイドレートされる際にクライアント側でデータを再取得することなく、サーバーからクライアントにレスポンスをNuxtペイロードに追加する処理を行います。

使用方法

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

カスタムのuseAsyncDataラッパーを使用している場合、予期しない動作を引き起こす可能性があるため、コンポーザブル内でawaitしないでください。カスタム非同期データフェッチャーの作成方法についてはこのレシピを参照してください。

datastatuserrorはVueのrefであり、<script setup>内で使用する際には.valueでアクセスする必要があります。一方、refresh/executeclearは通常の関数です。

パラメータの監視

組み込みの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]
  }
)

リアクティブキー

キーとしてcomputed ref、通常のref、またはゲッター関数を使用することで、キーが変更されたときに自動的に更新される動的なデータフェッチが可能です。

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

パラメータ

  • key: リクエスト間でデータフェッチを適切に重複排除するための一意のキー。キーを指定しない場合、useAsyncDataのインスタンスのファイル名と行番号に基づいて一意のキーが生成されます。
  • handler: 真値を返す必要がある非同期関数(例えば、undefinednullであってはならない)。そうでないと、クライアント側でリクエストが重複する可能性があります。

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呼び出しを行うと、それらは同じdataerrorstatusの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