Belajar Pinia - Actions & Async Logic
Episode 7 of 23

Belajar Pinia - Actions & Async Logic

Action adalah tempat logika mutasi dan efek samping di Pinia. Episode ini membahas action dasar, action async yang memanggil API dengan status loading dan error, serta action yang memanggil store lain. Kalian juga belajar pola reusability agar action bisa dipanggil dari komponen mana pun.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

State menyimpan data, getters menghitung turunan, dan actions membawa data ke dalam store. Action adalah method yang boleh mengubah state, memanggil API, mengatur timer, atau berkoordinasi dengan store lain — semua efek samping hidup di sini, bukan di komponen.

Episode 7 membahas action dari dasar sampai pola async production: action sinkron sederhana, action async dengan status loading dan error, serta action yang memanggil store lain. Di akhir episode, kalian akan punya pola action yang bisa dipakai komponen mana pun tanpa duplikasi logika.

Action Sederhana

Action dasar adalah method yang mengubah state. Di Options store, gunakan this; di Setup store, gunakan closure:

JSAction di Options store
export const useCartStore = defineStore('cart', {
  state: () => ({
    items: [] as { id: number; name: string; qty: number }[],
  }),
  actions: {
    addItem(item: { id: number; name: string }) {
      const existing = this.items.find((i) => i.id === item.id)
      if (existing) {
        existing.qty++
      } else {
        this.items.push({ ...item, qty: 1 })
      }
    },
    clear() {
      this.items = []
    },
  },
})

addItem(item) menerapkan logika bisnis (jika sudah ada, tambah qty; jika belum, push baru) dalam satu tempat. Komponen cukup memanggil store.addItem(item) — tidak ada duplikasi logika di setiap tombol.

Action Async dan Status Loading

Saat action memanggil API, simpan status loading dan error di state agar komponen bisa merender sesuai kondisi:

JSAction async dengan status
export const useUserStore = defineStore('user', {
  state: () => ({
    profile: null as { name: string } | null,
    loading: false,
    error: null as string | null,
  }),
  actions: {
    async fetchProfile() {
      this.loading = true
      this.error = null
      try {
        const res = await fetch('/api/profile')
        if (!res.ok) throw new Error('Gagal memuat profil')
        this.profile = await res.json()
      } catch (e) {
        this.error = e instanceof Error ? e.message : 'Terjadi kesalahan'
      } finally {
        this.loading = false
      }
    },
  },
})

Pola loading, error, lalu finally adalah standar untuk semua action async. this.loading = true di awal dan this.loading = false di finally menjamin status selalu benar, termasuk saat terjadi error.

Memanggil Store Lain dalam Action

Action boleh berkoordinasi dengan store lain lewat useXStore():

JSAction memanggil store lain
import { useAuthStore } from '@/stores/auth'
 
export const useCheckoutStore = defineStore('checkout', {
  state: () => ({ status: 'idle' as 'idle' | 'success' | 'error' }),
  actions: {
    async checkout() {
      const authStore = useAuthStore()
      if (!authStore.isLoggedIn) {
        await authStore.redirectToLogin()
        return
      }
      this.status = 'success'
    },
  },
})

useAuthStore() di dalam action memastikan store auth diaktifkan saat dibutuhkan. Ini adalah pola inti untuk composing stores, yang akan dibahas lebih dalam di episode 12.

Memakai Action Async di Komponen

Action async mengembalikan Promise, jadi komponen bisa menunggu hasilnya dan menangani sukses atau gagal:

JSPanggil action dari komponen
<script setup lang="ts">
import { useUserStore } from '@/stores/user'
 
const store = useUserStore()
 
async function muat() {
  await store.fetchProfile()
  if (store.error) {
    console.error(store.error)
  }
}
</script>

await store.fetchProfile() membuat komponen menunggu hingga action selesai. Action dipakai juga sebagai source of truth untuk status, sehingga UI bisa menampilkan spinner saat loading true dan pesan error saat error terisi.

Warning

Jangan panggil API langsung di komponen lalu menulis hasilnya ke store dengan store.$patch. Taruh seluruh alur di action — ini memudahkan testing (episode 17) dan menghindari logika tersebar.

Penutup

Episode 7 menutup segitiga dasar Pinia dengan actions. Kalian sekarang bisa menulis action sinkron dan async, mengelola status loading dan error, memanggil store lain dari dalam action, dan memakai action async dari komponen dengan await.

Inti yang harus dibawa pulang:

  • Action adalah tempat mutasi state dan efek samping.
  • Action async menyimpan loading dan error di state.
  • Selalu reset error dan set loading true di awal action.
  • finally menjamin loading mati di semua jalur.
  • Action bisa memanggil store lain dengan useXStore().
  • Panggil action dari komponen dengan await untuk mengikuti hasilnya.

Di episode 8 selanjutnya kita akan membahas plugin system Pinia — cara menambah properti global ke semua store, menerima opsi plugin, serta memakai $subscribe dan $onAction untuk observability. Ini membuka jalan untuk fitur seperti persistence di episode 9.