We use cookies to enhance your experience on the site
CodeWorlds

Composition API Stores (setup syntax)

At NOVA LAB, every system has its own configuration protocol. Pinia offers two styles for defining stores - Composition API (setup function) and Options API. Composition API is recommended because it's closer to how we write Vue 3 components.

Composition API vs Options API

1// Composition API (RECOMMENDED)
2export const useCounterStore = defineStore('counter', () => {
3  const count = ref(0)
4  const doubleCount = computed(() => count.value * 2)
5  function increment() { count.value++ }
6
7  return { count, doubleCount, increment }
8})
9
10// Options API
11export const useCounterStore = defineStore('counter', {
12  state: () => ({ count: 0 }),
13  getters: {
14    doubleCount: (state) => state.count * 2
15  },
16  actions: {
17    increment() { this.count++ }
18  }
19})

When to Choose Which Style?

| Aspect | Composition API | Options API | |--------|----------------|-------------| | Flexibility | Full | Limited | | TypeScript | Natural typing | Requires declarations | |

$reset()
| Must define manually | Works automatically | | Composables | Easy to use | More difficult | | Syntax | Like
<script setup>
| Like Vue Options API |

Using Composables in a Store

Composition API allows easy use of composables inside a store:

1import { defineStore } from 'pinia'
2import { ref, computed, watch } from 'vue'
3import { useLocalStorage } from '@vueuse/core'
4
5export const useSettingsStore = defineStore('settings', () => {
6  // Composable inside a store!
7  const theme = useLocalStorage('theme', 'dark')
8  const language = useLocalStorage('language', 'en')
9
10  const isDark = computed(() => theme.value === 'dark')
11
12  function toggleTheme() {
13    theme.value = isDark.value ? 'light' : 'dark'
14  }
15
16  return { theme, language, isDark, toggleTheme }
17})

Watchers in a Store

You can use

watch
and
watchEffect
inside a store:

1export const useAlertStore = defineStore('alerts', () => {
2  const temperature = ref(22)
3  const alerts = ref([])
4
5  // Watcher reacting to changes
6  watch(temperature, (newTemp, oldTemp) => {
7    if (newTemp > 50) {
8      alerts.value.push({
9        type: 'critical',
10        message: `Temperature critical: ${newTemp}°C`,
11        timestamp: Date.now()
12      })
13    }
14  })
15
16  function setTemperature(value) {
17    temperature.value = value
18  }
19
20  return { temperature, alerts, setTemperature }
21})

Typing with TypeScript

1interface CrewMember {
2  id: number
3  name: string
4  role: 'commander' | 'engineer' | 'scientist'
5  active: boolean
6}
7
8export const useCrewStore = defineStore('crew', () => {
9  const members = ref<CrewMember[]>([])
10  const selected = ref<CrewMember | null>(null)
11
12  const activeMembers = computed<CrewMember[]>(() =>
13    members.value.filter(m => m.active)
14  )
15
16  function addMember(member: Omit<CrewMember, 'id'>): CrewMember {
17    const newMember: CrewMember = {
18      ...member,
19      id: Date.now()
20    }
21    members.value.push(newMember)
22    return newMember
23  }
24
25  return { members, selected, activeMembers, addMember }
26})
Go to CodeWorlds