Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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, потому что:
- На сервере вычисляется один раз
- На клиенте состояние гидратируется (hydrate) из HTML
- Нет повторного запроса данных
Типизация 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 - глобальное состояние приложения (с ключом)
Практические советы
- Используй ключи уникально - 'auth.user', 'theme.mode'
- Composables для группировки - useAuth, useCart, useSettings
- Инициализация на сервере - используй process.server
- Гидрация данных - useState выполняет hydration автоматически
- Избегай мутаций - используй .value для изменения
useState в Nuxt - это мощный инструмент для управления глобальным состоянием с встроенной поддержкой SSR.