All skills
hyf0 avatar

/vue-pinia-best-practices

@bc922e4 official
by hyf0hyf0/vue-skills2.9k stars
167

Pinia stores, state management patterns, store setup, and reactivity with stores.

Use this Skill: https://skilld.dev/gh/hyf0/vue-skills/vue-pinia-best-practices

This session only. Nothing lands on disk.

referencepinia-no-active-pinia-error.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Fix "No Active Pinia" Error - Store Setup Timing

Impact: HIGH - The error "getActivePinia() was called but there was no active Pinia" is one of the most common Pinia errors. It occurs when you try to use a store before Pinia has been installed on the Vue app, causing your application to crash.

Task Checklist

  • Ensure app.use(pinia) is called before app.mount()
  • Ensure app.use(pinia) is called before app.use(router) if router guards use stores
  • Never call useXxxStore() in module-level (top-level) code
  • Only call useXxxStore() inside setup functions, composables, or after app initialization
  • Check for <script setup> vs <script> - the latter runs too early

The Error

[🍍]: "getActivePinia()" was called but there was no active Pinia.
Did you forget to install pinia?

Common Cause 1: Wrong Plugin Order

// main.js - WRONG ORDER
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router'  // Router uses a store in navigation guard
import App from './App.vue'

const app = createApp(App)

// WRONG: Router is installed first, but its guards use stores
app.use(router)  // Router guard calls useAuthStore() - FAILS!
app.use(createPinia())
app.mount('#app')

Fix: Install Pinia first:

// main.js - CORRECT ORDER
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import router from './router'
import App from './App.vue'

const app = createApp(App)

// CORRECT: Pinia installed before anything that uses stores
app.use(createPinia())
app.use(router)  // Now router guards can safely use stores
app.mount('#app')

Common Cause 2: Store Used at Module Level

// api.js - WRONG: Module-level store usage
import { useAuthStore } from '@/stores/auth'

// This runs immediately when the module is imported!
const authStore = useAuthStore()  // ERROR: No active Pinia yet

export function fetchUser() {
  return fetch('/api/user', {
    headers: {
      Authorization: `Bearer ${authStore.token}`
    }
  })
}

Fix: Call useStore inside functions:

// api.js - CORRECT: Store used inside function
import { useAuthStore } from '@/stores/auth'

export function fetchUser() {
  // Store is accessed when function is called, not when module loads
  const authStore = useAuthStore()

  return fetch('/api/user', {
    headers: {
      Authorization: `Bearer ${authStore.token}`
    }
  })
}

Common Cause 3: Script Tag Missing "setup"

<!-- WRONG: <script> runs before component setup -->
<script>
import { useUserStore } from '@/stores/user'

// This runs too early, before the component is set up
const userStore = useUserStore()  // ERROR!

export default {
  // ...
}
</script>

Fix: Use <script setup> or move to setup function:

<!-- CORRECT: <script setup> runs at the right time -->
<script setup>
import { useUserStore } from '@/stores/user'

// This runs during component setup, Pinia is active
const userStore = useUserStore()  // Works!
</script>
<!-- CORRECT: Options API with setup function -->
<script>
import { useUserStore } from '@/stores/user'

export default {
  setup() {
    // Called during component initialization
    const userStore = useUserStore()  // Works!
    return { userStore }
  }
}
</script>

Common Cause 4: mapStores with Parentheses

<script>
import { mapStores } from 'pinia'
import { useProductsStore } from '@/stores/products'

export default {
  computed: {
    // WRONG: Called the function instead of passing it
    ...mapStores(useProductsStore())  // ERROR!
  }
}
</script>

Fix: Pass the function reference, not the result:

<script>
import { mapStores } from 'pinia'
import { useProductsStore } from '@/stores/products'

export default {
  computed: {
    // CORRECT: Pass the function without calling it
    ...mapStores(useProductsStore)  // No parentheses!
  }
}
</script>

Common Cause 5: Router Guards Before Pinia

// router/index.js - WRONG
import { createRouter } from 'vue-router'
import { useAuthStore } from '@/stores/auth'

const router = createRouter({ /* ... */ })

// This guard is registered immediately
router.beforeEach((to) => {
  // When this runs during app startup, Pinia might not be ready
  const authStore = useAuthStore()  // May fail!

  if (to.meta.requiresAuth && !authStore.isLoggedIn) {
    return '/login'
  }
})

Fix: Use lazy store access or ensure plugin order:

// router/index.js - CORRECT
import { createRouter } from 'vue-router'

const router = createRouter({ /* ... */ })

router.beforeEach((to) => {
  // Dynamically import to avoid module-level execution
  const { useAuthStore } = await import('@/stores/auth')
  const authStore = useAuthStore()

  if (to.meta.requiresAuth && !authStore.isLoggedIn) {
    return '/login'
  }
})

// OR ensure main.js has correct order:
// app.use(pinia)
// app.use(router)

Debugging Checklist

When you see "No active Pinia":

  1. Check main.js order: Is app.use(pinia) before other plugins?
  2. Search for top-level useStore calls: Any store usage outside functions/setup?
  3. Check script tags: Using <script> instead of <script setup>?
  4. Check mapStores usage: Using useStore() instead of useStore?
  5. Check import chains: Does an early import trigger store usage?

Safe Pattern: Conditional Store Access

// For code that might run before Pinia is ready
import { getActivePinia } from 'pinia'

export function safelyUseStore() {
  const pinia = getActivePinia()

  if (!pinia) {
    console.warn('Pinia not initialized yet')
    return null
  }

  const { useUserStore } = await import('@/stores/user')
  return useUserStore()
}

Reference

Source: SKILL.md on GitHub

No alerts16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides educational content and best practices for Pinia state management in Vue.js applications. It is a documentation-focused skill with no malicious patterns detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer7mo

    7 files scanned · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at bc922e4. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 8 months ago
version
1.0.0
author
github.com/vuejs-ai

README badge

README badge for hyf0/vue-skills/vue-pinia-best-practices

Teaches Pinia store setup, reactivity patterns, and state management conventions for Vue applications. Covers common mistakes like destructuring breaking reactivity, setup stores missing state in DevTools, and losing method context in templates.

Generated from the current SKILL.md.

What does this skill cover?
Pinia store setup, state management patterns, reactivity gotchas, and common errors like getActivePinia and broken destructuring in Vue components.
Does this skill address SSR with Pinia?
Yes. It includes guidance on setup stores missing state in DevTools or SSR environments.
How does this handle filter state across page refreshes?
The skill references patterns for persisting ephemeral filters using URL state rather than relying on store alone.
Does this cover store method binding issues?
Yes. It addresses the gotcha where store methods lose context when called directly in templates and explains the parentheses solution.

Generated from the current SKILL.md. These answers refresh after source changes.