皆さん、こんにちは。
今日は「Nuxt3:useAsyncDataの基本的な使い方」についてご紹介します。
Nuxt 3 系以降(Nuxt Bridge / Nuxt 4 などを含む)の新しいデータ取得方法として、asyncDataや fetchが従来(Nuxt 2 系)のオプション・フックから、Composableという仕組みに変わりました。具体的には、useAsyncData・useFetchといった関数を使ってデータ取得・SSR を行います。
なお、2025年2月時点で“Nuxt 4”は公式の安定版としてまだ公開されていません。
一般的には、Nuxt 3(Nuxt Bridge経由で 2から3への移行などを含む)でのデータ取得方法として useAsyncDataが広く利用されています。
Nuxt 4が正式にリリースされた際も、useAsyncDataやuseFetchをベースとしたデータ取得の流れはほぼ同様になると考えられます。
Nuxt 3 (あるいは Nuxt 4 で想定されるほぼ同等の書き方) をベースに、useAsyncData の使い方を解説します。
useAsyncData の基本的な使い方
useAsyncData は サーバーサイドでのデータ取得 (SSR) とクライアントサイドでの再利用 の両方を手軽に行える Composable です。次のような流れになります。
-
useAsyncData(key, handler, options?)の呼び出し - 返ってきた
{ data, pending, error, refresh, ... }オブジェクトを利用してテンプレートやスクリプトで扱う - サーバーサイドでの初回描画時には Nuxt がデータを取得し、HTML に埋め込む
- クライアントサイドでは埋め込まれたデータを再利用し、再度の取得を不要にする(オプションにより再度フェッチさせることも可能)
サンプルコード
<template>
<div>
<h1>ユーザー情報</h1>
<!-- データが取得できたら表示 -->
<div v-if="data">
<p>ID: {{ data.id }}</p>
<p>Name: {{ data.name }}</p>
</div>
<!-- 読み込み中の場合 -->
<div v-else-if="pending">
<p>Loading...</p>
</div>
<!-- エラーが発生した場合 -->
<div v-else-if="error">
<p style="color: red;">Error: {{ error.message }}</p>
</div>
<!-- 手動で再取得したい場合 -->
<button @click="refresh">Refresh</button>
</div>
</template>
<script setup>
// useAsyncData composable をインポート
// Nuxt 3 / 4 の場合はデフォルトで使えるため明示的なインポート不要の場合も
// import { useAsyncData } from '#app';
const { data, pending, error, refresh } = await useAsyncData(
// 第1引数: キャッシュ用のキー (ユニークな文字列推奨)
'fetchUser',
// 第2引数: データ取得処理
() => $fetch('/api/user')
// 第3引数(オプション):
// {
// // server: false にすると SSR 時にはリクエストしないなどの設定も可能
// // lazy: true にするとページ描画後に非同期でフェッチを行う
// }
)
</script>
- data: 取得したデータが返る(ref でラップされている)
- pending: リクエストの進行状況(true なら通信中)
- error: 何らかのエラーが発生した場合の情報(null でないならエラー発生)
- refresh: 再度データ取得を実行するためのメソッド
useFetchとの違い
Nuxt 3/4 には同じようにデータ取得を行うuseFetchというComposableも用意されています。
-
useFetch(url, options?):fetch APIを内部的に利用 -
useAsyncData(key, handler, options?):$fetch(軽量な Fetch ラッパ) を利用
useFetchは内部的に ブラウザの標準fetchを使う点が大きな特徴で、レスポンスやエラーハンドリングなどはよりブラウザ標準に近い形で行われます。一方、$fetchにはデフォルトで credentialsやヘッダー周りの扱い、エラー処理の違いなど、Nuxt 独自の利便性が加わっています。
SSR とキャッシュ
useAsyncDataは SSR 中に取得されたデータをクライアントサイドに埋め込み、クライアント遷移時の無駄なリクエストを省く ことができます。たとえばユーザーがページ遷移して戻ってきた際にも、キャッシュ済みのデータを再利用する設定が可能です。
// options パラメータの例
const { data } = await useAsyncData('fetchUser', () => $fetch('/api/user'), {
default: () => ({ id: 0, name: '' }), // デフォルト値
transform: (rawData) => rawData.user, // レスポンスの整形
watch: false, // リアクティブな値の変更で再フェッチするかどうか
immediate: true, // 初回読み込みですぐにフェッチするか
lazy: false, // SSR 完了後、クライアントでロード時にフェッチするか
// ...etc
})
API ルートの例 (/api/user)
上記サンプルの'/api/user'は、サーバーサイドでデータを返すエンドポイントとして想定しています。Nuxt 3/4 ではserver/api/以下にファイルを置くだけで API ルートを定義でき、エンドポイントと SSR が同居 する形になります。
たとえばserver/api/user.tsというファイルを作って以下のようにすると、'/api/user'でアクセスできます。
export default defineEventHandler(async (event) => {
// ここでデータベースや外部APIにアクセスしたりする
// 一旦ダミーデータを返す
return {
id: 1,
name: 'Taro Nuxt'
}
})
まとめ
-
Nuxt 4であってもNuxt 3同様、useAsyncDataやuseFetchを使うことでサーバーサイドレンダリング + クライアントでのデータ再利用を簡単に実現できる。 -
useAsyncDataとuseFetchの使い分けは好みによるところが大きい。useAsyncDataで$fetchを使う場合のほうがNuxt独自の利便性が得られる一方、標準fetchになじみがあればuseFetchでもOK。 -
Composableによりコードの見通しやテストがしやすくなっているので、適切にキーやオプションを設定してSSR + CSRのデータ取得を最適化する。
現時点でまだ“Nuxt 4”は正式な情報が十分出ていない状況ですが、Nuxt 3 での useAsyncData の利用方法がそのまま応用できると考えて問題ありません。
ぜひ参考にしてみてください。
今日は以上です。
ありがとうございました。
よろしくお願いいたします。