← Назад к вопросам

Как сделать чтобы useAsyncData отрабатывал только на клиенте?

2.2 Middle🔥 122 комментариев
#Инструменты и DevOps

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI4 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение для клиентского выполнения useAsyncData в Nuxt 3

В Nuxt 3 useAsyncData по умолчанию выполняется как на сервере (во время SSR), так и на клиенте (при навигации). Чтобы ограничить его выполнение только клиентской стороной, существует несколько подходов.

Основные подходы

1. Использование флага server: false

Самый простой и рекомендуемый способ — явно указать параметр server: false:

const { data, pending, error, refresh } = await useAsyncData(
  'client-only-data',
  () => $fetch('/api/client-data'),
  {
    server: false, // Ключевая опция
    lazy: false, // Опционально: загружать сразу или при монтировании
    immediate: true // Опционально: выполнять немедленно
  }
)

Преимущества:

  • Четкое и явное указание намерений
  • Оптимизация производительности (исключает серверный вызов)
  • Предотвращает гидратационные ошибки

2. Использование useFetch с тем же флагом

Для запросов API можно использовать useFetch с аналогичным подходом:

const { data, pending, error } = await useFetch('/api/client-data', {
  server: false,
  key: 'client-fetch'
})

3. Условное выполнение с помощью process.client

Более явный, но менее элегантный подход с проверкой окружения:

const fetchClientData = async () => {
  if (process.client) {
    const response = await $fetch('/api/client-data')
    return response
  }
  return null // Возвращаем null для серверного рендеринга
}

const { data } = await useAsyncData(
  'conditional-data',
  fetchClientData
)

Практические сценарии использования

Случай 1: Зависимость от браузерных API

Когда данные требуют доступа к localStorage, sessionStorage или другим браузерным API:

const { data: userPreferences } = await useAsyncData(
  'user-prefs',
  () => {
    if (typeof window !== 'undefined') {
      const theme = localStorage.getItem('theme')
      const language = localStorage.getItem('language')
      return { theme, language }
    }
    return null
  },
  { server: false }
)

Случай 2: Интеграция с сторонними библиотеками

При работе с библиотеками, которые существуют только в браузере:

const { data: geolocation } = await useAsyncData(
  'location',
  async () => {
    if ('geolocation' in navigator) {
      return new Promise((resolve) => {
        navigator.geolocation.getCurrentPosition((position) => {
          resolve({
            lat: position.coords.latitude,
            lng: position.coords.longitude
          })
        })
      })
    }
    return null
  },
  { server: false }
)

Важные нюансы и лучшие практики

Гидратация и состояние

При использовании server: false важно учитывать:

  • На сервере данные будут null или undefined
  • На клиенте произойдет асинхронная загрузка
  • Может потребоваться обработка состояния загрузки:
<template>
  <div>
    <div v-if="pending">Загрузка данных...</div>
    <div v-else-if="error">Ошибка: {{ error.message }}</div>
    <div v-else>{{ data }}</div>
  </div>
</template>

Кэширование и производительность

  • Данные с server: false не кэшируются на сервере
  • Для повторных запросов используйте refresh():
// Обновление данных
const refreshData = () => {
  refresh()
}

// Автоматическое обновление каждые 30 секунд
onMounted(() => {
  const interval = setInterval(refresh, 30000)
  onUnmounted(() => clearInterval(interval))
})

Альтернативный подход: onMounted

Для простых случаев можно использовать композицию onMounted:

const clientData = ref(null)

onMounted(async () => {
  clientData.value = await $fetch('/api/client-data')
})

Сравнение подходов:

  • useAsyncData с server: false: лучше для интеграции с экосистемой Nuxt
  • onMounted: проще, но меньше возможностей (нет pending, error состояний)

Рекомендации по архитектуре

  1. Четкое разделение ответственности: Серверные данные — для SEO и первоначальной загрузки, клиентские — для интерактивности
  2. Обработка ошибок: Всегда предусматривайте сценарии ошибок при клиентских запросах
  3. Индикация загрузки: Показывайте состояние pending для улучшения UX
  4. Ключи запросов: Используйте уникальные ключи для предотвращения конфликтов кэша
// Полный пример с обработкой ошибок
const {
  data: userData,
  pending: isLoading,
  error: loadError,
  refresh: reloadUserData
} = await useAsyncData(
  `user-profile-${userId}`,
  () => $fetch(`/api/users/${userId}`),
  {
    server: false,
    onError: (error) => {
      console.error('Ошибка загрузки:', error)
      // Можно добавить отправку в систему мониторинга
    }
  }
)

Выбор подхода зависит от конкретных требований вашего приложения, но использование server: false в useAsyncData является наиболее идиоматичным способом для Nuxt 3 при необходимости выполнения запросов только на клиенте.