\n```\n\nЕсли несколько компонентов вызовут useCounter(), они получат одно и то же состояние!\n\n## useState с функцией инициализации\n\nВторой аргумент - это функция, которая инициализирует состояние.\n\n```typescript\n// Инициализация с функцией\nconst user = useState('user', () => ({\n id: 1,\n name: 'Alice',\n email: 'alice@example.com'\n}));\n\n// Инициализация с функцией, которая вызывает API\nconst posts = useState('posts', async () => {\n const { data } = await useFetch('/api/posts');\n return data;\n});\n\n// Проверка, уже ли инициализировано\nconst items = useState('items', () => {\n if (process.server) {\n // На сервере инициализируем\n return [];\n }\n // На клиенте используем существующее значение\n return [];\n});\n```\n\n## useState vs useAsyncData\n\nДля асинхронного состояния в Nuxt используется useAsyncData или useFetch.\n\n```typescript\n// useState для синхронного состояния\nconst theme = useState('theme', () => 'light');\n\n// useAsyncData для асинхронного состояния\nconst { data: user, pending, error } = await useAsyncData('user', () => \n $fetch('/api/user')\n);\n\n// useFetch - обёртка над useAsyncData\nconst { data: posts } = await useFetch('/api/posts');\n```\n\n## Composable с useState\n\nОбычно useState используется внутри composables для разделяемого состояния.\n\n```typescript\n// composables/useAuth.ts\nexport const useAuth = () => {\n const user = useState('auth.user', () => null);\n const token = useState('auth.token', () => '');\n \n const login = async (email: string, password: string) => {\n const data = await $fetch('/api/login', {\n method: 'POST',\n body: { email, password }\n });\n \n user.value = data.user;\n token.value = data.token;\n \n // Установи cookie для SSR\n useCookie('auth-token').value = data.token;\n };\n \n const logout = () => {\n user.value = null;\n token.value = '';\n };\n \n return { user, token, login, logout };\n};\n\n// Использование в компоненте\nconst { user, login, logout } = useAuth();\n\nawait login('user@example.com', 'password');\nconsole.log(user.value); // { id: 1, email: '...' }\n```\n\n## useState и SSR (Server-Side Rendering)\n\nЭто главное отличие от React. useState в Nuxt работает на сервере и на клиенте.\n\n```typescript\n// На сервере инициализируется один раз\nconst data = useState('data', () => {\n console.log('Инициализация'); // Выведется один раз на сервере\n return fetchData();\n});\n\n// На клиенте это же значение переиспользуется\n// Нет повторной инициализации!\n```\n\nЭто очень эффективно для SSR, потому что:\n1. На сервере вычисляется один раз\n2. На клиенте состояние гидратируется (hydrate) из HTML\n3. Нет повторного запроса данных\n\n## Типизация useState\n\n```typescript\ninterface User {\n id: number;\n name: string;\n email: string;\n}\n\nconst user = useState('user', () => ({\n id: 0,\n name: '',\n email: ''\n}));\n\n// TypeScript знает тип\nuser.value.name = 'John'; // OK\nuser.value.age = 30; // Error!\n```\n\n## Сравнение с React\n\n```typescript\n// React\nconst [count, setCount] = useState(0);\nsetCount(count + 1);\n\n// Nuxt\nconst count = useState('count', () => 0);\ncount.value++;\n\n// React - локальное состояние компонента\n// Nuxt - глобальное состояние приложения (с ключом)\n```\n\n## Практические советы\n\n1. **Используй ключи уникально** - 'auth.user', 'theme.mode'\n2. **Composables для группировки** - useAuth, useCart, useSettings\n3. **Инициализация на сервере** - используй process.server\n4. **Гидрация данных** - useState выполняет hydration автоматически\n5. **Избегай мутаций** - используй .value для изменения\n\nuseState в Nuxt - это мощный инструмент для управления глобальным состоянием с встроенной поддержкой SSR.","dateCreated":"2026-04-03T17:55:08.603902","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как работает useState в Nuxt.js?

1.7 Middle🔥 231 комментариев
#Vue.js

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

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

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

useState в Nuxt.js - Composable API

в Nuxt.js (версия 3+) используется Vue 3 Composition API. useState - это специальный composable, который создаёт реактивное состояние. В отличие от React, это работает несколько иначе.

// В Nuxt.js используется usestate для создания реактивного состояния
import { useState } from '#app';

export default defineComponent({
  setup() {
    const count = useState('count', () => 0);
    
    const increment = () => {
      count.value++;
    }
    
    return { count, increment };
  }
});

Важный момент: в Nuxt useState возвращает Ref объект, а не кортеж [state, setState] как в React. Доступ к значению через .value.

usestate vs ref и reactive

в Nuxt есть несколько способов создать реактивное состояние:

import { useState, ref, reactive } from '#app';

// useState - используется для разделяемого состояния (SSR-friendly)
const counter = useState('counter', () => 0);

// ref - локальное состояние компонента
const localCount = ref(0);

// reactive - для объектов
const user = reactive({
  name: 'John',
  email: 'john@example.com'
});

Главное отличие: useState создаёт состояние на уровне приложения, которое сохраняется при SSR, а ref и reactive - только локальное состояние компонента.

useState с ключом (key)

Первый аргумент useState - это уникальный ключ, который идентифицирует состояние во всём приложении.

// counter.ts (composable)
export const useCounter = () => {
  // Это состояние будет общим для всего приложения
  const count = useState('counter', () => 0);
  
  const increment = () => count.value++;
  const decrement = () => count.value--;
  
  return { count, increment, decrement };
};

// page.vue
<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>

<script setup>
const { count, increment, decrement } = useCounter();
</script>

Если несколько компонентов вызовут useCounter(), они получат одно и то же состояние!

useState с функцией инициализации

Второй аргумент - это функция, которая инициализирует состояние.

// Инициализация с функцией
const user = useState('user', () => ({
  id: 1,
  name: 'Alice',
  email: 'alice@example.com'
}));

// Инициализация с функцией, которая вызывает API
const posts = useState('posts', async () => {
  const { data } = await useFetch('/api/posts');
  return data;
});

// Проверка, уже ли инициализировано
const items = useState('items', () => {
  if (process.server) {
    // На сервере инициализируем
    return [];
  }
  // На клиенте используем существующее значение
  return [];
});

useState vs useAsyncData

Для асинхронного состояния в Nuxt используется useAsyncData или useFetch.

// useState для синхронного состояния
const theme = useState('theme', () => 'light');

// useAsyncData для асинхронного состояния
const { data: user, pending, error } = await useAsyncData('user', () => 
  $fetch('/api/user')
);

// useFetch - обёртка над useAsyncData
const { data: posts } = await useFetch('/api/posts');

Composable с useState

Обычно useState используется внутри composables для разделяемого состояния.

// composables/useAuth.ts
export const useAuth = () => {
  const user = useState('auth.user', () => null);
  const token = useState('auth.token', () => '');
  
  const login = async (email: string, password: string) => {
    const data = await $fetch('/api/login', {
      method: 'POST',
      body: { email, password }
    });
    
    user.value = data.user;
    token.value = data.token;
    
    // Установи cookie для SSR
    useCookie('auth-token').value = data.token;
  };
  
  const logout = () => {
    user.value = null;
    token.value = '';
  };
  
  return { user, token, login, logout };
};

// Использование в компоненте
const { user, login, logout } = useAuth();

await login('user@example.com', 'password');
console.log(user.value); // { id: 1, email: '...' }

useState и SSR (Server-Side Rendering)

Это главное отличие от React. useState в Nuxt работает на сервере и на клиенте.

// На сервере инициализируется один раз
const data = useState('data', () => {
  console.log('Инициализация'); // Выведется один раз на сервере
  return fetchData();
});

// На клиенте это же значение переиспользуется
// Нет повторной инициализации!

Это очень эффективно для SSR, потому что:

  1. На сервере вычисляется один раз
  2. На клиенте состояние гидратируется (hydrate) из HTML
  3. Нет повторного запроса данных

Типизация useState

interface User {
  id: number;
  name: string;
  email: string;
}

const user = useState<User>('user', () => ({
  id: 0,
  name: '',
  email: ''
}));

// TypeScript знает тип
user.value.name = 'John'; // OK
user.value.age = 30;       // Error!

Сравнение с React

// React
const [count, setCount] = useState(0);
setCount(count + 1);

// Nuxt
const count = useState('count', () => 0);
count.value++;

// React - локальное состояние компонента
// Nuxt - глобальное состояние приложения (с ключом)

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

  1. Используй ключи уникально - 'auth.user', 'theme.mode'
  2. Composables для группировки - useAuth, useCart, useSettings
  3. Инициализация на сервере - используй process.server
  4. Гидрация данных - useState выполняет hydration автоматически
  5. Избегай мутаций - используй .value для изменения

useState в Nuxt - это мощный инструмент для управления глобальным состоянием с встроенной поддержкой SSR.