🏪 Global State vs Local State: когда глобальное хранилище — это overkill

В разработке часто встречаю паттерн: создают глобальный store для данных, которые используются в одном месте. Разберем, когда это оправдано, а когда — избыточно.

Что такое глобальный store?

Это состояние, живущее на уровне всего приложения. Обновил данные в одном компоненте — они актуальны везде. Классический пример: информация о пользователе (токен, email, имя) — singleton на всю систему.

Когда глобальный store оправдан?

✅ Данные используются в нескольких местах ✅ Должны быть одинаковыми везде ✅ Изменения нужно синхронизировать ✅ Логика работы с данными инкапсулирована

Примеры: useAuthStore(), useCurrentUserStore(), useThemeStore()

Цена глобального состояния

Store — не бесплатная штука. Вот что получаете в нагрузку:

1. Ручная синхронизация Создали сущность → обновить store Удалили сущность → обновить store Отредактировали → обновить store

Пропустили хоть один случай — state устарел.

2. Проблемы многопользовательских приложений // Пользователь А: удалил элемент, store обновлен await deleteItem(id) items.value = items.value.filter(i => i.id !== id)

// Пользователь Б: тоже удалил элемент через 2 минуты // Пользователь А об этом НЕ знает (нет WebSocket/SSE)

// Пользователь А открывает список через 5 минут // Store показывает 2 элемента, на сервере их 1 // Попытка использовать удаленный элемент → ошибка 404

Без real-time коммуникации между клиентами store становится источником багов.

3. Cache invalidation Одна из сложнейших проблем, когда инвалидировать store? - Каждую минуту? - При каждом монтировании компонента? - При фокусе на вкладке? - При возврате на страницу?

Нет универсального ответа — только трейдоффы.

Альтернатива: локальное состояние // В компоненте const items = ref([])

const fetchItems = async () => { items.value = await getItems() }

// Запрашиваем когда нужно onMounted(() => fetchItems()) // Или при открытии dropdown // Или по клику на кнопку

Что получили:

✅ Всегда актуальные данные ✅ Не думаем о синхронизации ✅ Нет race conditions между пользователями ✅ Проще понять и поддерживать ✅ Меньше связанности (coupling)

Пример: список для dropdown // ❌ Overkill: глобальный store const categoriesStore = ref([])

export function useCategoriesStore() { const getAll = async () => { categoriesStore.value = await fetchCategories() } return { categories: categoriesStore, getAll } }

// Используется только в одной форме // Нужна синхронизация при CRUD // Может устареть в многопользовательской среде

// ✅ Просто и работает: локальное состояние const categories = ref([])

const loadCategories = async () => { categories.value = await fetchCategories() }

// Запрашиваем при открытии @dropdown-open="loadCategories"

Когда НЕ нужен global store?

❌ Данные используются локально (одна форма/компонент) ❌ Актуальность важнее кэширования ❌ Нет сложной бизнес-логики вокруг данных ❌ Многопользовательская среда без real-time sync ❌ Данные быстро меняются Вывод

Глобальный store — мощный инструмент, но не панацея.

Правило: Используй самое простое решение, которое работает. Усложняй только когда появляется реальная потребность.

Не стройте архитектуру "на вырост" — YAGNI (You Aren't Gonna Need It).

Чеклист выбора Использовать global store: - Данные в 3+ компонентах - Нужна единая точка истины - Есть сложная логика управления - Real-time синхронизация между клиентами

Использовать local state: - Данные в 1-2 компонентах - Важна актуальность - Простая логика загрузки - Нет real-time инфраструктуры

Золотое правило: Начинай с локального состояния. Рефактори в global store, когда появится боль от дублирования.

Сталкивались с проблемами из-за избыточного использования глобального состояния? 💬

#vue #architecture #statemanagement #frontend #bestpractices