brand logo

ドキュメント

useNuxtData

データフェッチコンポーザブルの現在のキャッシュ値にアクセスします。

useNuxtData は、useAsyncDatauseLazyAsyncDatauseFetchuseLazyFetch の現在のキャッシュ値に、明示的に提供されたキーを使用してアクセスできます。

使用方法

useNuxtData コンポーザブルは、useAsyncDatauseLazyAsyncDatauseFetchuseLazyFetch などのデータフェッチコンポーザブルの現在のキャッシュ値にアクセスするために使用されます。データフェッチ時に使用したキーを提供することで、キャッシュされたデータを取得し、必要に応じて使用できます。

これは、既にフェッチされたデータを再利用したり、Optimistic Updates やカスケードデータ更新のような機能を実装したりすることで、パフォーマンスを最適化するのに特に有用です。

useNuxtData を使用するには、データフェッチコンポーザブル(useFetchuseAsyncData など)が明示的にキーを提供して呼び出されていることを確認してください。

パラメータ

  • key: キャッシュされたデータを識別する一意のキー。このキーは、元のデータフェッチ時に使用したものと一致する必要があります。

戻り値

  • data: 提供されたキーに関連付けられたキャッシュデータへのリアクティブな参照。キャッシュデータが存在しない場合、値は null になります。この Ref はキャッシュデータが変更されると自動的に更新され、コンポーネント内でシームレスなリアクティビティを可能にします。

以下の例は、サーバーから最新のデータがフェッチされる間、キャッシュされたデータをプレースホルダーとして使用する方法を示しています。

pages/posts.vue
// 後で 'posts' キーを使用して同じデータにアクセスできます
const { data } = await useFetch('/api/posts', { key: 'posts' })
pages/posts/[id\
// posts.vue(親ルート)での useFetch のキャッシュ値にアクセス
const { data: posts } = useNuxtData('posts')

const route = useRoute()

const { data } = useLazyFetch(`/api/posts/${route.params.id}`, {
  key: `post-${route.params.id}`,
  default() {
    // キャッシュから個々の投稿を見つけてデフォルト値として設定します。
    return posts.value.find(post => post.id === route.params.id)
  }
})

楽観的更新

以下の例は、useNuxtData を使用して楽観的更新を実装する方法を示しています。

楽観的更新は、サーバー操作が成功することを前提に、ユーザーインターフェースを即座に更新する手法です。操作が最終的に失敗した場合、UI は以前の状態にロールバックされます。

pages/todos.vue
// 後で 'todos' キーを使用して同じデータにアクセスできます
const { data } = await useAsyncData('todos', () => $fetch('/api/todos'))
components/NewTodo.vue
const newTodo = ref('')
let previousTodos = []

// todos.vue での useAsyncData のキャッシュ値にアクセス
const { data: todos } = useNuxtData('todos')

async function addTodo () {
  return $fetch('/api/addTodo', {
    method: 'post',
    body: {
      todo: newTodo.value
    },
    onRequest () {
      // フェッチが失敗した場合に復元するために、以前のキャッシュ値を保存します。
      previousTodos = todos.value

      // 楽観的に todos を更新します。
      todos.value = [...todos.value, newTodo.value]
    },
    onResponseError () {
      // リクエストが失敗した場合、データをロールバックします。
      todos.value = previousTodos
    },
    async onResponse () {
      // リクエストが成功した場合、バックグラウンドで todos を無効化します。
      await refreshNuxtData('todos')
    }
  })
}

useNuxtData<DataT = any> (key: string): { data: Ref<DataT | undefined> }

tips

このセクションは公式ドキュメントの翻訳ではなく、本サイト独自の補足記事です。

useNuxtData の補足解説

Nuxt でのデータフェッチは、useAsyncDatauseFetch などのコンポーザブルを使うことで簡単に行えますが、これらのデータは内部的にキャッシュされており、useNuxtData を使うことでそのキャッシュに直接アクセスできます。この記事では、useNuxtData の利点や使いどころ、実務での具体的な活用例、そして注意すべきポイントを丁寧に解説します。


1. イントロ:なぜ useNuxtData が便利なのか?

Nuxt アプリケーションでは、同じデータを複数のコンポーネントやページで共有したい場面が多くあります。useNuxtData は、すでにフェッチ済みのデータを再利用できるため、無駄な API コールを減らし、ユーザー体験の向上やパフォーマンスの最適化に貢献します。

また、楽観的更新(Optimistic Updates)などの高度な UI 操作も、useNuxtData を使うことで実装しやすくなります。これにより、サーバー応答を待たずに即座に UI を更新し、レスポンスが遅い場合でもユーザーに快適な操作感を提供可能です。


2. まず結論:useNuxtData のポイント

  • キャッシュされたデータにリアクティブにアクセス可能
    既にフェッチされたデータをリアクティブな Ref として取得できる。

  • キーによるデータ識別が必須
    データフェッチ時に指定したキーを使ってキャッシュを参照する。

  • パフォーマンス最適化に有効
    不要な再フェッチを防ぎ、API 呼び出し回数を削減できる。

  • 楽観的更新の実装が容易
    UI の即時更新と失敗時のロールバックを簡単に行える。

  • SSR と CSR の両方で動作
    サーバーサイドレンダリングとクライアントサイドレンダリングの両方でキャッシュを共有可能。


3. いつ使うべきか?使わない方がよいケースは?

使うべきケース

  • 複数ページやコンポーネント間で同じデータを共有したいとき
    例:ブログ記事一覧と詳細ページで同じ記事データを使い回す。

  • API 呼び出しの回数を減らしてパフォーマンスを向上させたいとき
    既に取得済みのデータを再利用することで、無駄な通信を防ぐ。

  • 楽観的更新を実装したいとき
    ユーザー操作に即座に反応しつつ、失敗時に元に戻す処理を行う。

  • データのキャッシュ状態をリアクティブに監視したいとき
    キャッシュの変化に応じて UI を動的に更新できる。

使わない方がよいケース

  • キーを指定していないデータフェッチには使えない
    useAsyncDatauseFetch でキーを指定しない場合、キャッシュにアクセスできない。

  • データの整合性が非常に重要で、常に最新の情報を取得したい場合
    キャッシュを使うことで古いデータを参照してしまうリスクがあるため、都度フェッチが望ましい。

  • キャッシュの状態管理が複雑になりすぎる場合
    大規模な状態管理が必要な場合は Vuex や Pinia などの状態管理ライブラリを検討したほうが良い。


4. 実務でよくあるユースケースとサンプルコード

ユースケース1:親ページで取得したデータを子ページで再利用する

親ページで記事一覧を取得し、子ページで個別記事を表示する際に、親ページのキャッシュを利用して初期表示を高速化します。

// 親ページで記事一覧を取得(キーは 'posts')
const { data: posts } = await useFetch('/api/posts', { key: 'posts' })
// 子ページで親ページのキャッシュを利用
const { data: posts } = useNuxtData('posts')
const route = useRoute()

const { data } = useLazyFetch(`/api/posts/${route.params.id}`, {
  key: `post-${route.params.id}`,
  default() {
    return posts.value?.find(post => post.id === route.params.id)
  }
})

ユースケース2:楽観的更新による即時 UI 反映

ToDo リストの追加操作を楽観的に更新し、サーバー応答を待たずに UI を更新。失敗時は元に戻します。

const newTodo = ref('')
let previousTodos = []

const { data: todos } = useNuxtData('todos')

async function addTodo() {
  return $fetch('/api/addTodo', {
    method: 'post',
    body: { todo: newTodo.value },
    onRequest() {
      previousTodos = [...todos.value]
      todos.value = [...todos.value, newTodo.value]
    },
    onResponseError() {
      todos.value = previousTodos
    },
    async onResponse() {
      await refreshNuxtData('todos')
    }
  })
}

ユースケース3:複数コンポーネントでのデータ共有

同じ API データを複数のコンポーネントで使い回し、API 呼び出しを一度に抑制。

const { data: userData } = await useAsyncData('user', () => $fetch('/api/user'))
// 別コンポーネントでキャッシュを参照
const { data: userData } = useNuxtData('user')

5. よくある落とし穴・注意点

SSR と CSR の違いによるキャッシュの扱い

  • サーバーサイドレンダリング時にキャッシュされたデータは、クライアントにシリアライズされて引き継がれますが、クライアント側での再フェッチやキャッシュ更新のタイミングに注意が必要です。

  • クライアント側でキャッシュが存在しない場合、useNuxtDatanull を返すため、必ず存在チェックを行いましょう。

Hydration(ハイドレーション)時の不整合

  • サーバーでレンダリングされた HTML とクライアントの初期状態が異なると、Hydration エラーが発生することがあります。キャッシュデータの初期値やデフォルト値の設定は慎重に行いましょう。

パフォーマンスへの影響

  • キャッシュを過度に更新すると、リアクティブなデータの変更が多発し、パフォーマンス低下を招く可能性があります。必要なタイミングでのみ更新する設計が重要です。

キーの一意性を保つこと

  • キャッシュキーはユニークである必要があります。同じキーを複数の異なるデータに使うと、意図しないデータの上書きや参照ミスが起こります。

6. まとめ

useNuxtData は、Nuxt のデータフェッチキャッシュに直接アクセスできる強力なツールです。適切に使うことで API 呼び出しの削減や UI の即時更新が可能になり、ユーザー体験の向上に寄与します。一方で、SSR/CSR の違いやキャッシュの整合性、パフォーマンス面での注意も必要です。

実務では、親子コンポーネント間のデータ共有や楽観的更新などで特に効果を発揮します。キー管理を徹底し、キャッシュの状態を正しく扱うことで、Nuxt アプリケーションの開発効率と品質を高めましょう。


useNuxtData を使う際は、必ず元のデータフェッチでキーを指定していることを確認してください。キーがないとキャッシュにアクセスできません。

楽観的更新を実装する場合は、失敗時のロールバック処理を忘れずに実装しましょう。UI の不整合を防ぐために重要です。