Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

Actions w Pinia

Actions to funkcje modyfikujące state i wykonujące operacje - jak komendy kontroli misji NOVA LAB. To tu znajduje się logika biznesowa: pobieranie danych, walidacja, obsługa błędów.

Podstawowe actions

W Composition API actions to zwykłe funkcje:

1import { defineStore } from 'pinia'
2import { ref } from 'vue'
3
4export const useCrewStore = defineStore('crew', () => {
5  const members = ref([])
6  const selectedMember = ref(null)
7
8  // Prosta action
9  function selectMember(member) {
10    selectedMember.value = member
11  }
12
13  // Action z logiką
14  function addMember(member) {
15    if (members.value.length >= 8) {
16      throw new Error('Maximum crew size reached!')
17    }
18    members.value.push({
19      ...member,
20      id: Date.now(),
21      joinedAt: new Date()
22    })
23  }
24
25  function removeMember(id) {
26    members.value = members.value.filter(m => m.id !== id)
27    if (selectedMember.value?.id === id) {
28      selectedMember.value = null
29    }
30  }
31
32  return { members, selectedMember, selectMember, addMember, removeMember }
33})

Asynchroniczne actions

Actions mogą być asynchroniczne - idealne do pobierania danych z API:

1export const useCrewStore = defineStore('crew', () => {
2  const members = ref([])
3  const isLoading = ref(false)
4  const error = ref(null)
5
6  async function fetchCrew() {
7    isLoading.value = true
8    error.value = null
9
10    try {
11      const response = await fetch('/api/crew')
12      if (!response.ok) {
13        throw new Error('Failed to fetch crew data')
14      }
15      members.value = await response.json()
16    } catch (e) {
17      error.value = e.message
18    } finally {
19      isLoading.value = false
20    }
21  }
22
23  async function updateMemberRole(id, newRole) {
24    try {
25      const response = await fetch(`/api/crew/${id}`, {
26        method: 'PATCH',
27        headers: { 'Content-Type': 'application/json' },
28        body: JSON.stringify({ role: newRole })
29      })
30
31      if (!response.ok) throw new Error('Update failed')
32
33      const updated = await response.json()
34      const index = members.value.findIndex(m => m.id === id)
35      if (index !== -1) {
36        members.value[index] = updated
37      }
38    } catch (e) {
39      error.value = e.message
40      throw e
41    }
42  }
43
44  return { members, isLoading, error, fetchCrew, updateMemberRole }
45})

Obsługa błędów w actions

Wzorzec try/catch/finally jest standardem w asynchronicznych actions:

1async function saveData(data) {
2  isLoading.value = true
3  error.value = null
4
5  try {
6    const result = await apiCall(data)
7    // Sukces - aktualizuj state
8    items.value.push(result)
9    return result
10  } catch (e) {
11    // Błąd - zapisz komunikat
12    error.value = e.message
13    throw e // Przekaż błąd do komponentu
14  } finally {
15    // Zawsze - wyłącz loading
16    isLoading.value = false
17  }
18}

Wywoływanie actions z komponentu

1<script setup>
2import { onMounted } from 'vue'
3import { useCrewStore } from '@/stores/crew'
4
5const crewStore = useCrewStore()
6
7// Wywołanie przy montowaniu
8onMounted(() => {
9  crewStore.fetchCrew()
10})
11
12// Handler z obsługą błędu
13async function handleAddMember(member) {
14  try {
15    await crewStore.addMember(member)
16  } catch (e) {
17    alert('Error: ' + e.message)
18  }
19}
20</script>
Vai a CodeWorlds