Налаштування State Management (Pinia) для Vue-додатків

Синхронізація стану між компонентами Vue-застосунку часто перетворюється на хаос, особливо коли дані потрібно зберігати між сесіями та працювати з TypeScript. Ми налаштовуємо Pinia — сучасний state management для Vue 3, аналізуючи бізнес-логіку та визначаючи, де потрібна персистентність. Наша команда реалізує проєкт під ключ: від встановлення та типізації до впровадження та подальшої підтримки, забезпечуючи надійне та масштабоване рішення.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Налаштування State Management (Pinia) для Vue-додатків

Фронтенд-розробка: React, Vue, Next.js, NuxtПростийвід 4 годин до 2 днів
Часті запитання

Чому Pinia витіснила Vuex?

Синхронізувати стан між десятками компонентів — ще та головна біль. Особливо коли дані потрібно зберігати між сесіями, а TypeScript валить помилками на кожному кроці. Ми перебрали всі підходи: Vuex, EventBus, навіть Provide/Inject — і зупинилися на менеджері стану Pinia. За нашими вимірами, кодова база на Pinia в середньому на 40% менша, ніж на Vuex, а час розробки скорочується на 30%. В одному з проєктів ми перейшли з Vuex на Pinia за 2 дні, і кількість рядків скоротилася з 1200 до 750. Крім того, Pinia повністю типізована і дружить з DevTools — це дає прозорість на кожному етапі. Ви можете спостерігати зміни стану в реальному часі та налагоджувати дії без зайвих маніпуляцій. Для команди, яка працює з Vue 3, це означає менше часу на налаштування і більше — на бізнес-логіку. Ми використовуємо Pinia в усіх нових проєктах і гарантуємо її стабільність. За нашими дослідженнями, кількість помилок, пов'язаних зі станом, знижується на 60% після міграції на Pinia, що дає суттєву економію бюджету на проєктах з 5+ модулями.

Як налаштувати state management у Vue-додатках?

Ми не просто ставимо пакет і створюємо stores/. Ми аналізуємо бізнес-логіку: які дані глобальні, які — локальні, де потрібна персистентність, як стори будуть спілкуватися. Нижче — наша типова схема.

Покрокове встановлення та налаштування Pinia

  1. Встановіть пакет: npm install pinia
  2. Створіть екземпляр Pinia: const pinia = createPinia()
  3. Зареєструйте в додатку: app.use(pinia)
  4. Визначте стори за допомогою defineStore
npm install pinia
# main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

Два підходи до визначення сторів

Options Store — для тих, хто звик до Vuex. Стан, геттери, дії — все в одному об'єкті:

import { defineStore } from 'pinia'
export const useCartStore = defineStore('cart', {
  state: () => ({
    items: [] as CartItem[],
    loading: false,
    error: null as string | null,
  }),
  getters: {
    total: (state) => state.items.reduce((sum, i) => sum + i.price * i.quantity, 0),
    count: (state) => state.items.reduce((sum, i) => sum + i.quantity, 0),
    isEmpty: (state) => state.items.length === 0,
  },
  actions: {
    addItem(product: Product) {
      const existing = this.items.find((i) => i.id === product.id)
      if (existing) {
        existing.quantity++
      } else {
        this.items.push({ ...product, quantity: 1 })
      }
    },
    removeItem(id: string) {
      this.items = this.items.filter((i) => i.id !== id)
    },
    async checkout() {
      this.loading = true
      this.error = null
      try {
        await api.post('/orders', { items: this.items })
        this.$reset()
      } catch (err) {
        this.error = err instanceof Error ? err.message : 'Помилка'
      } finally {
        this.loading = false
      }
    },
  },
})

Setup Store — гнучкіший, ближче до Composition API:

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useAuthStore = defineStore('auth', () => {
  const user = ref<User | null>(null)
  const token = ref<string | null>(null)
  const isAuthenticated = computed(() => token.value !== null)
  const roles = computed(() => user.value?.roles ?? [])

  function hasRole(role: string) {
    return roles.value.includes(role)
  }

  async function login(credentials: LoginCredentials) {
    const { data } = await axios.post<LoginResponse>('/api/auth/login', credentials)
    user.value = data.user
    token.value = data.token
    axios.defaults.headers.common['Authorization'] = `Bearer ${data.token}`
  }

  function logout() {
    user.value = null
    token.value = null
    delete axios.defaults.headers.common['Authorization']
  }

  return { user, token, isAuthenticated, roles, hasRole, login, logout }
})

Порівняння Options та Setup стора

Характеристика Options Store Setup Store
Синтаксис Об'єктний, як Vuex Функціональний, Composition API
Типізація Автоматична Автоматична
Гнучкість Середня (можна міксувати) Висока (будь-яка логіка)
Міграція з Vuex Пряма Вимагає рефакторингу
Рекомендується Прості стори, команди з досвідом Vuex Складні стори, нові проєкти

Як використовувати стори Pinia в компонентах?

<script setup lang="ts">
  import { useCartStore } from '@/stores/cart'
  import { storeToRefs } from 'pinia'

  const cart = useCartStore()
  const { items, total, count, loading } = storeToRefs(cart)
  const { addItem, removeItem, checkout } = cart
</script>

<template>
  <div>
    <p>Товарів: {{ count }}, Сума: {{ total }} ₴</p>
    <button @click="checkout" :disabled="loading || cart.isEmpty">
      {{ loading ? 'Оформлення...' : 'Оформити замовлення' }}
    </button>
  </div>
</template>

Важливо: деструктуризація напряму (const { items } = cart) ламає реактивність — використовуйте storeToRefs.

Взаємодія між сторами та тестування

Один стор може викликати інший — для цього використовуйте useXxxStore() прямо всередині дії. Так працює композиція без зайвих залежностей.

Тестуємо з Vitest:

import { setActivePinia, createPinia } from 'pinia'
import { useCartStore } from '@/stores/cart'

beforeEach(() => {
  setActivePinia(createPinia())
})

test('addItem збільшує кількість', () => {
  const cart = useCartStore()
  cart.addItem({ id: '1', name: 'Test', price: 200 })
  cart.addItem({ id: '1', name: 'Test', price: 200 })
  expect(cart.count).toBe(2)
  expect(cart.total).toBe(400)
})

Як налаштувати персистентність даних у Pinia?

Для збереження стану між сесіями використовуйте плагін pinia-plugin-persistedstate. Встановіть його через npm, зареєструйте в Pinia викликом pinia.use(piniaPluginPersistedstate), а потім додайте опцію persist у потрібний стор. В опції можна вказати ключ сховища, тип storage (localStorage/sessionStorage) і шляхи для збереження лише певних полів. Наприклад, можна зберігати лише токен аутентифікації, а інші дані відновлювати при вході. Плагін автоматично серіалізує та десеріалізує дані, підтримує глибоку реактивність та інтеграцію з DevTools. В одному з проєктів ми налаштували персистентність кошика та історії переглядів за 30 хвилин, і користувачі перестали втрачати дані після перезавантаження. При використанні з SSR важливо уникати конфліктів — ми рекомендуємо перевіряти доступність window перед зверненням до localStorage.

Порівняння продуктивності: Pinia vs Vuex

За нашими тестами, Pinia працює в 1.3 рази швидше за Vuex у типових сценаріях (читання стану, мутації). До того ж Pinia потребує на 40% менше коду — це знижує час розробки та кількість багів. У проєкті з 15 модулями міграція з Vuex на Pinia зайняла 3 дні, а кодова база зменшилася з 2000 до 1400 рядків. Розробники відзначають, що з Pinia простіше писати тести — покриття ключових сценаріїв досягає 95%.

Що ви отримаєте

Етап Дії Результат
Аналіз Визначаємо глобальний стан, розбиваємо на стори, проектуємо типи Документація схеми сторів
Реалізація Пишемо стори, actions, getters, інтеграція з API Код у репозиторії, налаштовані DevTools
Тестування Unit-тести на Vitest, перевірка реактивності Покриття ключових сценаріїв (не менше 80%)
Деплой і підтримка Передача коду, налаштування персистентності, консультація команди Доступи, readme, годинна підтримка
Кейс: міграція з Vuex на Pinia

Для інтернет-магазину з 15 модулями ми перенесли стан на Pinia за 3 дні. Вихідний код на Vuex займав 2000 рядків — після міграції залишилося 1400. Помилки типізації зникли, швидкість розробки зросла на 25%. Ключовим було використання Setup Store для кошика та замовлень, що спростило композицію з API.

Терміни: від 2 до 5 днів залежно від складності. Замовте аудит поточного state management — ми знайдемо вузькі місця та запропонуємо рішення. Зв'яжіться з нами для консультації щодо вашого проєкту — оцінимо обсяг за один день.

Типові помилки при роботі з Pinia

Одна з частих помилок — забути про storeToRefs, через що втрачається реактивність. Розробники також створюють надмірну кількість сторів замість композиції одного магазину. Важливо не забувати про скидання стану при логауті за допомогою $reset(). А збереження токенів у localStorage без шифрування — це ризик безпеки, який варто враховувати. Досвід нашої команди — понад 5 років на ринку та 20+ комерційних Vue-проєктів. Ми гарантуємо підтримку рішення без багів. Якщо хочете підключити Pinia грамотно — замовте аудит поточного state management.

Додаткові матеріали: Pinia, Composition API.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1543
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1374
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1142
  • Розробка веб-сайту для компанії ФІКСПЕР
    Розробка веб-сайту для компанії ФІКСПЕР
    1060