Skip to content

Stores

IONFLOW uses Pinia for state management. Stores handle global application state that needs to be shared across components.

Pinia stores provide:

  • Centralized state management
  • DevTools integration
  • TypeScript support
  • Modular architecture
StoreLocationDescription
useAuthStoresrc/stores/auth.tsAuthentication and user state
useCounterStoresrc/stores/counter.tsExample counter store

Manages authentication state, user information, and company context.

import { useAuthStore } from '@/stores/auth';
PropertyTypeDescription
userUser | nullCurrent user
companyCompany | nullCurrent company/tenant
tokenstring | nullAuth token
isAuthenticatedbooleanAuthentication status
GetterReturn TypeDescription
fullNamestringUser’s full name
isAdminbooleanAdmin role check
companyIdnumber | nullCurrent company ID
ActionParametersDescription
login(credentials)Authenticate user
logout()Clear session
setUser(user)Update user data
setCompany(company)Set active company
refreshToken()Refresh auth token
import { useAuthStore } from '@/stores/auth';
const auth = useAuthStore();
// Access state
console.log(auth.user);
console.log(auth.isAuthenticated);
// Use getters
console.log(auth.fullName);
console.log(auth.isAdmin);
// Call actions
await auth.login({ email, password });
auth.logout();
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useExampleStore = defineStore('example', () => {
// State
const items = ref<Item[]>([]);
const selectedId = ref<string | null>(null);
const loading = ref(false);
// Getters
const selectedItem = computed(() => items.value.find(item => item.id === selectedId.value));
const itemCount = computed(() => items.value.length);
// Actions
const fetchItems = async () => {
loading.value = true;
try {
items.value = await api.getItems();
} finally {
loading.value = false;
}
};
const selectItem = (id: string) => {
selectedId.value = id;
};
const reset = () => {
items.value = [];
selectedId.value = null;
};
return {
// State
items,
selectedId,
loading,
// Getters
selectedItem,
itemCount,
// Actions
fetchItems,
selectItem,
reset,
};
});
Use CaseSolution
Global app state (auth, theme)Pinia Store
Server state (API data)TanStack Query
Local component stateref() / reactive()
Reusable logicComposable

✅ Use stores for:

  • Authentication state
  • User preferences
  • Global UI state (sidebar, modals)
  • Application configuration

❌ Don’t use stores for:

  • Server data (use TanStack Query)
  • Form state (use VeeValidate)
  • Local component state
// Use composition API style (setup stores)
export const useStore = defineStore('name', () => {
// ...
});
// Type everything
const items = ref<Item[]>([]);
// Use getters for derived state
const total = computed(() => items.value.length);
// Keep actions focused
const addItem = (item: Item) => {
items.value.push(item);
};
// Don't use any
const data: any = ref(null);
// Don't mutate state directly from components
store.items.push(newItem); // Bad!
store.addItem(newItem); // Good!
// Don't store server data in Pinia
// Use TanStack Query instead

For persisting store state (e.g., to localStorage):

import { defineStore } from 'pinia';
import { useStorage } from '@vueuse/core';
export const usePreferencesStore = defineStore('preferences', () => {
const theme = useStorage('theme', 'light');
const language = useStorage('language', 'en');
return { theme, language };
});

Pinia integrates with Vue DevTools:

  1. Install Vue DevTools extension
  2. Open DevTools
  3. Navigate to “Pinia” tab
  4. Inspect store state and history