Работа с данными в Nuxt с помощью useNuxtData

12 октября 2026
Автор

Олег Марков

Введение

Когда вы работаете над современным веб-приложением, задача получения и управления асинхронными данными часто выходит на первый план. В Nuxt для загрузки данных есть useFetch и useAsyncData, а рядом с ними — небольшая, но очень полезная composable-функция useNuxtData. Её часто понимают неправильно, поэтому давайте сразу расставим точки над i.

useNuxtData ничего не загружает. Она даёт вам доступ к данным, которые уже лежат в кеше Nuxt — то есть к результату более раннего вызова useFetch или useAsyncData с тем же ключом. Это синхронная функция: её не нужно вызывать через await, и она не возвращает ни pending, ни error, ни refresh.

Звучит скромно, но именно на этом строятся два очень практичных приёма: мгновенное отображение данных при переходе между страницами и оптимистичные обновления интерфейса. Их мы и разберём.

Все примеры в статье написаны для Nuxt 3 и Nuxt 4 — API useNuxtData в этих версиях одинаков. В Nuxt 2 этой функции нет.

Эффективное получение и передача данных - это основа для создания динамичных и интерактивных Nuxt-приложений. Но для оптимизации этого процесса необходимо понимать, как работают различные методы получения данных, как кэшировать запросы и как обрабатывать большие объемы данных. Если вы хотите узнать больше о способах получения и передачи данных в Nuxt, приходите на наш большой курс Nuxt - fullstack Vue фреймворк. На курсе 129 уроков и 13 упражнений, AI-тренажеры для безлимитной практики с кодом и задачами 24/7, решение задач с живым ревью наставника, еженедельные встречи с менторами.

Курс по теме

Курс Nuxt с нуля

40 000+ студентов · рейтинг 4.8 · гарантия возврата 30 дней

Что такое useNuxtData

useNuxtData — это composable-функция Nuxt, которая возвращает реактивную ссылку на данные, сохранённые в payload приложения под указанным ключом.

// Единственный аргумент — ключ, под которым данные были закешированы
const { data } = useNuxtData('users')

Разберём, что здесь происходит:

  • 'users' — ключ кеша. Тот же самый ключ, который вы передали в useFetch или useAsyncData;
  • data — это Ref. Если под таким ключом уже есть данные, вы получите их сразу; если нет — внутри будет null;
  • вызов синхронный. await useNuxtData(...) писать не нужно — там нечего ждать.

Обратите внимание на важное следствие: если никто ещё не загружал данные под этим ключом, data.value будет null, и это нормальная штатная ситуация, которую нужно обрабатывать.

Откуда в кеше берутся данные

Кеш заполняют функции загрузки. Ключ можно задать явно:

// Явный ключ — так вы точно знаете, по какому имени данные окажутся в кеше
const { data: users } = await useFetch('/api/users', { key: 'users' })

Если ключ не указать, Nuxt сгенерирует его автоматически на основе места вызова. Такой ключ непредсказуем, поэтому для работы с useNuxtData всегда задавайте ключ явно.

Чем useNuxtData отличается от useFetch и useAsyncData

Это разные инструменты, а не альтернативы друг другу:

Загружает данные Возвращает Нужен await
useFetch да, делает HTTP-запрос data, status, error, refresh, clear да
useAsyncData да, выполняет вашу функцию data, status, error, refresh, clear да
useNuxtData нет, только читает кеш data нет

То есть useNuxtData не заменяет загрузку данных — она работает поверх уже загруженных данных.

Сценарий 1: мгновенный показ данных при переходе на страницу

Это самый частый и самый выигрышный сценарий. Представьте список постов и страницу отдельного поста. Когда пользователь кликает по посту из списка, заголовок и краткое описание у нас уже есть — они лежат в кеше списка. Значит, можно показать их немедленно, не заставляя пользователя смотреть на спиннер.

Сначала страница со списком — здесь мы задаём ключ явно:

<!-- pages/posts.vue -->
<script setup>
// Ключ 'posts' пригодится нам на странице отдельного поста
const { data: posts } = await useFetch('/api/posts', { key: 'posts' })
</script>

<template>
  <ul>
    <li v-for="post in posts" :key="post.id">
      <NuxtLink :to="`/posts/${post.id}`">{{ post.title }}</NuxtLink>
    </li>
  </ul>
</template>

Теперь страница поста. Смотрите, как здесь используется кеш:

<!-- pages/posts/[id].vue -->
<script setup>
const route = useRoute()
const id = route.params.id

// Достаём из кеша список, загруженный на предыдущей странице
const { data: posts } = useNuxtData('posts')

const { data: post } = await useFetch(`/api/posts/${id}`, {
  key: `post-${id}`,
  // Пока идёт запрос, показываем данные из кеша списка
  default() {
    return posts.value?.find((p) => p.id === Number(id))
  }
})
</script>

<template>
  <article v-if="post">
    <h1>{{ post.title }}</h1>
    <p>{{ post.body }}</p>
  </article>
</template>

Что мы получили: пользователь видит заголовок поста сразу при переходе, а полный текст подставляется, когда приходит ответ сервера. Если же пользователь открыл страницу поста напрямую по ссылке, кеш будет пуст, default() вернёт undefined, и страница просто отрисуется после загрузки — никакой ошибки не произойдёт.

Сценарий 2: оптимистичные обновления

Второй сценарий — когда вы хотите обновить интерфейс до того, как сервер подтвердит изменение. Пользователь добавил задачу — она сразу появилась в списке; если сервер вернул ошибку, откатываем изменение назад.

<script setup>
// Читаем тот же список, что загружен через useFetch с ключом 'todos'
const { data: todos } = useNuxtData('todos')

async function addTodo(todo) {
  // Сохраняем предыдущее состояние, чтобы было к чему откатиться
  const previous = todos.value ? [...todos.value] : []

  // Обновляем UI немедленно
  todos.value = [...previous, todo]

  try {
    await $fetch('/api/todos', { method: 'POST', body: todo })
  } catch (error) {
    // Запрос не прошёл — возвращаем список в исходное состояние
    todos.value = previous
  } finally {
    // В любом случае синхронизируемся с сервером
    await refreshNuxtData('todos')
  }
}
</script>

Здесь todos.value = ... меняет именно тот Ref, который вернул useFetch на другой странице или в другом компоненте — данные в кеше общие. Поэтому изменение подхватят все места, где этот ключ используется.

Как обновлять и очищать кеш

У самой useNuxtData нет метода refresh — обновлением занимаются отдельные утилиты Nuxt.

refreshNuxtData

Перезапускает загрузку для указанного ключа (или для всех ключей, если вызвать без аргументов):

// Перезагрузить данные под конкретным ключом
await refreshNuxtData('todos')

// Перезагрузить сразу несколько ключей
await refreshNuxtData(['todos', 'users'])

clearNuxtData

Удаляет данные из кеша, не запуская загрузку заново:

// Данные под ключом 'todos' будут сброшены в null
clearNuxtData('todos')

Это удобно при выходе пользователя из аккаунта, когда закешированные данные больше показывать нельзя.

refresh из useFetch

Если вы находитесь в том же компоненте, где вызывали useFetch, проще воспользоваться его собственным refresh:

const { data, refresh } = await useFetch('/api/todos', { key: 'todos' })

// Кнопку «Обновить» вешаем прямо на refresh

Статусы загрузки и ошибки

Раз useNuxtData не загружает данные, у неё нет и статусов загрузки. Индикатор загрузки и ошибку берите из той функции, которая данные загружает:

<script setup>
// status и error приходят из useFetch, а не из useNuxtData
const { data: todos, status, error, refresh } = await useFetch('/api/todos', {
  key: 'todos'
})
</script>

<template>
  <div v-if="status === 'pending'">Загрузка...</div>
  <div v-else-if="error">Ошибка: {{ error.message }}</div>
  <ul v-else>
    <li v-for="todo in todos" :key="todo.id">{{ todo.title }}</li>
  </ul>
  <button @click="refresh" :disabled="status === 'pending'">Обновить</button>
</template>

Важный момент, о который часто спотыкаются: если вы написали await useFetch(...), то к моменту следующей строки загрузка уже завершена. Проверять status сразу после await в скрипте бессмысленно — он никогда не будет 'pending'. Индикатор загрузки имеет смысл только в шаблоне, где он реагирует на реактивные изменения, либо при вызове useFetch без await (например, с опцией lazy: true).

Типизация

useNuxtData принимает тип-параметр, поэтому вы можете описать форму данных:

interface Todo {
  id: number
  title: string
  done: boolean
}

// data будет иметь тип Ref<Todo[] | null>
const { data: todos } = useNuxtData<Todo[]>('todos')

Значение null в типе — не случайность: оно напоминает, что кеш может быть пуст, и это нужно обработать.

Практические советы

  1. Всегда задавайте ключ явно в useFetch и useAsyncData — без этого вы не сможете достучаться до данных через useNuxtData.
  2. Используйте осмысленные префиксы в ключах — post-42 вместо 42, user-profile-42 вместо profile. Это защищает от коллизий.
  3. Не пишите await перед useNuxtData — функция синхронная, и await только запутает читателя кода.
  4. Всегда проверяйте data.value на null — кеш может быть пуст, если пользователь открыл страницу напрямую.
  5. Для обновления используйте refreshNuxtData, а для полной очистки — clearNuxtData.

Заключение

useNuxtData — это небольшой, но точный инструмент: доступ к уже загруженным данным по ключу. Она не делает запросов и не управляет их жизненным циклом — за это отвечают useFetch и useAsyncData. Зато она позволяет переиспользовать данные между страницами и компонентами, показывать пользователю содержимое мгновенно и делать оптимистичные обновления с честным откатом при ошибке.

Работа с данными - это один из ключевых аспектов веб-разработки. Чтобы создавать гибкие и масштабируемые приложения, необходимо освоить все возможности фреймворка, включая работу с сервером, базами данных и API. На нашем курсе Nuxt - fullstack Vue фреймворк вы найдете все необходимые знания и навыки для достижения успеха. В первых 3 модулях уже доступно бесплатное содержание — начните погружаться в Nuxt прямо сегодня.

Частозадаваемые технические вопросы по теме статьи и ответы на них

Почему useNuxtData возвращает null?

Значит, под этим ключом в кеше ничего нет. Самые частые причины: данные ещё не загружались (пользователь открыл страницу напрямую), в useFetch не был задан ключ явно, либо ключи не совпадают по написанию. Проверьте, что в обоих местах используется одна и та же строка.

Как обновить данные, если useNuxtData не возвращает refresh?

Используйте refreshNuxtData('ключ') — эта утилита доступна глобально и перезапускает загрузку для указанного ключа. Если вы находитесь в компоненте, где вызывался useFetch, берите refresh прямо из его результата.

Можно ли использовать useNuxtData в middleware или плагине?

Да, вызывать её можно. Но помните, что она только читает кеш: если данные ещё не загружены, вы получите null. Для загрузки данных в middleware используйте useAsyncData или $fetch.

Что делать, если данные зависят от параметров маршрута?

Включите параметр в ключ при загрузке, а затем читайте по тому же ключу:

const route = useRoute()
const { data } = await useFetch(`/api/user/${route.params.id}`, {
  key: `user-${route.params.id}`
})

// В другом компоненте
const { data: user } = useNuxtData(`user-${route.params.id}`)

Как очистить кеш при выходе пользователя из аккаунта?

Вызовите clearNuxtData со списком ключей, которые относятся к пользовательским данным:

clearNuxtData(['user-profile', 'todos', 'notifications'])

Данные под этими ключами станут null, и при следующем запросе будут загружены заново.

Стрелочка влевоКак отключить определенные функции в NuxtНастройка и использование cookie в NuxtСтрелочка вправо

Постройте личный план изучения Nuxt до уровня Middle — бесплатно!

Nuxt — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Nuxt

Генерация статического сайта с помощью NuxtКак использовать useAsyncData в NuxtКак использовать SVG в NuxtКоманды для запуска NuxtРабота с JSON-данными в NuxtКак настроить HTML-шаблон в NuxtГенерация статического сайта с помощью NuxtРуководство по получению данных с Fetch в NuxtКак отключить определенные функции в NuxtРабота с данными в Nuxt с помощью useNuxtDataНастройка и использование cookie в NuxtГайд по аутентификации (auth) в NuxtКак создавать API-маршруты в Nuxt
Использование Vite для ускорения разработки в NuxtКак запустить Nuxt-приложение в productionРуководство по использованию TypeScript в NuxtКак работает Server-Side Rendering SSR в NuxtНастройка и оптимизация серверной части Nuxt-приложенияРуководство по настройке маршрутизации в NuxtКакие проекты разумно реализовывать на NuxtИнструкция по управлению пакетами NPM в NuxtИнтеграция Node.js для Nuxt-приложенияНастройка мета-тегов для SEO в NuxtНастройка и использование HTTPS в NuxtКак отлавливать и обрабатывать ошибки в NuxtКак развернуть Nuxt приложение в DockerРуководство по развертыванию приложений в Nuxt CloudКак оптимизировать сборку на NuxtИнтеграция Laravel и Nuxt
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Nuxt

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга5.0
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий