Belajar Nuxt - State Management
Episode 7 of 24

Belajar Nuxt - State Management

Episode ini membahas pengelolaan state global dengan Pinia di Nuxt: mendefinisikan stores dengan syntax setup dan options, plugins Pinia, pola shared state dengan composables, serta cara sinkronisasi state saat SSR hydration.

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

Pendahuluan

Saat aplikasi tumbuh, banyak komponen butuh data yang sama — misalnya isi keranjang belanja yang ditampilkan di header, halaman keranjang, dan halaman checkout sekaligus. Melempar data lewat props berlapis membuat kode sulit dirawat. Jawabannya adalah state global dengan Pinia, store resmi Vue.

Episode 7 membahas Pinia di dalam Nuxt: cara mengaktifkan module-nya, dua cara mendefinisikan store, plugins untuk memperluas store, serta isu paling rumit dalam SSR — bagaimana memastikan state tidak bocor antar user dan tersinkronisasi dengan benar saat hydration.

State Global dengan Pinia

Mengaktifkan Module Pinia

Install module resmi Pinia untuk Nuxt:

Install Pinia
npm install @pinia/nuxt pinia
JSDaftarkan di nuxt.config
export default defineNuxtConfig({
  modules: ["@pinia/nuxt"],
})

Setelah module terdaftar, kalian bisa membuat store di folder app/stores dan memakainya di mana pun tanpa import module — store yang dipanggil akan dibuat dan dibagikan secara otomatis.

Membuat Store Keranjang

Mari buat store keranjang belanja untuk project belajar-shop:

JSapp/stores/keranjang.ts
export const useKeranjangStore = defineStore("keranjang", {
  state: () => ({
    items: [] as { id: string; nama: string; harga: number }[],
  }),
  getters: {
    total: (state) =>
      state.items.reduce((jumlah, item) => jumlah + item.harga, 0),
  },
  actions: {
    tambah(item: { id: string; nama: string; harga: number }) {
      this.items.push(item)
    },
    kosongkan() {
      this.items = []
    },
  },
})

defineStore("keranjang", {...}) mendefinisikan store dengan state, getters, dan actions. Getters menghitung nilai turunan, actions memuat mutasi state — keduanya bisa dipakai dari komponen mana pun.

Setup Store vs Options Store

Setup Store untuk Logika Kompleks

Selain syntax options di atas, Pinia mendukung syntax setup yang mirip komponen:

JSSetup store
export const useKatalogStore = defineStore("katalog", () => {
  const produk = ref([])
  const total = computed(() => produk.value.length)
 
  async function muat() {
    produk.value = await $fetch("/api/produk")
  }
 
  return { produk, total, muat }
})

Pilih berdasarkan kompleksitas: options store lebih deklaratif dan mudah dibaca, setup store lebih fleksibel untuk logika yang memakai computed dan fungsi pembantu.

Memakai Store di Komponen

JSGunakan store di komponen
const keranjang = useKeranjangStore()
 
function tambahKeKeranjang(produk) {
  keranjang.tambah({ id: produk.id, nama: produk.nama, harga: produk.harga })
}

useKeranjangStore() dipanggil di komponen untuk mengakses instance store. Seluruh komponen yang memakai store yang sama otomatis saling tersinkronasi.

Pinia Plugins

Memperluas Kemampuan Store

Plugin Pinia adalah fungsi yang dijalankan untuk setiap store yang dibuat. Gunanya untuk menambahkan behavior global seperti logging atau persistence:

JSapp/plugins/keranjang-persist.ts
export default defineNuxtPlugin(() => {
  const pinia = usePinia()
  pinia.use((context) => {
    context.store.$subscribe((mutation, state) => {
      console.log("Store berubah", mutation.type)
    })
  })
})

pinia.use((context) => {...}) mendaftarkan plugin yang menerima setiap store baru. Di sini $subscribe dipakai untuk memantau perubahan state — berguna untuk analytics atau logging.

Composition API untuk Shared State

State Ringan Tanpa Pinia

Untuk state yang sangat kecil dan lokal, Nuxt menyediakan useState — composable untuk shared state yang aman untuk SSR:

JSShared state dengan useState
export function usePromo() {
  return useState("promo", () => "GRATIS-ONGKIR")
}

useState("promo", () => "GRATIS-ONGKIR") membuat state reaktif yang dibagikan antar komponen dan aman dipakai di server maupun client. Gunakan ini untuk data ringan, dan Pinia untuk state bisnis yang kompleks dengan getters serta actions.

State Hydration dan SSR Store Sync

Bahaya State Global di Server

Saat SSR, satu request bisa menangani banyak user bersamaan. Jika state global diinisialisasi di luar komponen, data antar user bisa tercampur. Karena itu store Pinia di Nuxt dibuat per-request — setiap request mendapat instance store sendiri, sehingga tidak ada kebocoran data.

Hydration yang Konsisten

Pinia di Nuxt menyalurkan state dari server ke client lewat payload. Kunci suksesnya: state store harus diinisialisasi di server dan client dengan cara yang sama.

JSInisialisasi store saat SSR
if (import.meta.server) {
  const keranjang = useKeranjangStore()
  await keranjang.muatDariServer()
}

Pola if (import.meta.server) di atas memuat data awal hanya di server, lalu state otomatis tersinkronisasi ke client saat hydration. Hindari membaca data user secara asinkron langsung di state store tanpa inisialisasi yang konsisten.

Penutup

Episode 7 menutup lapisan state Nuxt: Pinia sebagai state management global dengan options dan setup store, plugins untuk memperluas store, useState untuk shared state ringan, serta pemahaman penting bahwa store di Nuxt dibuat per-request agar tidak bocor antar user saat SSR.

Inti yang harus dibawa pulang:

  • Aktifkan Pinia dengan module @pinia/nuxt dan simpan store di app/stores.
  • defineStore mendukung syntax options dan setup; pilih sesuai kebutuhan.
  • Getters untuk nilai turunan, actions untuk mutasi state.
  • Plugins Pinia ditambahkan lewat pinia.use dan bisa menambah behavior global.
  • useState adalah alternatif ringan untuk shared state yang aman SSR.
  • Store Pinia dibuat per-request di SSR — jangan simpan state user di module scope.

Di episode 8 selanjutnya kita akan membahas configuration dan runtime config — mengelola nuxt.config.ts, runtime config untuk env variables public dan private, konfigurasi modules, serta build optimizations dan feature flags. Toko kalian akan mulai diatur dengan benar.