Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
116 lines
2.2 KiB
Markdown
116 lines
2.2 KiB
Markdown
---
|
|
name: using-stores-outside-components
|
|
description: Correctly using stores in navigation guards, plugins, and other non-component contexts
|
|
---
|
|
|
|
# Using Stores Outside Components
|
|
|
|
Stores need the `pinia` instance, which is automatically injected in components. Outside components, you may need to provide it manually.
|
|
|
|
## Single Page Applications
|
|
|
|
Call stores **after** pinia is installed:
|
|
|
|
```ts
|
|
import { useUserStore } from '@/stores/user'
|
|
import { createPinia } from 'pinia'
|
|
import { createApp } from 'vue'
|
|
import App from './App.vue'
|
|
|
|
// ❌ Fails - pinia not created yet
|
|
const userStore = useUserStore()
|
|
|
|
const pinia = createPinia()
|
|
const app = createApp(App)
|
|
app.use(pinia)
|
|
|
|
// ✅ Works - pinia is active
|
|
const userStore = useUserStore()
|
|
```
|
|
|
|
## Navigation Guards
|
|
|
|
**Wrong:** Call at module level
|
|
|
|
```ts
|
|
import { createRouter } from 'vue-router'
|
|
const router = createRouter({ /* ... */ })
|
|
|
|
// ❌ May fail depending on import order
|
|
const store = useUserStore()
|
|
|
|
router.beforeEach((to) => {
|
|
if (store.isLoggedIn) { /* ... */ }
|
|
})
|
|
```
|
|
|
|
**Correct:** Call inside the guard
|
|
|
|
```ts
|
|
router.beforeEach((to) => {
|
|
// ✅ Called after pinia is installed
|
|
const store = useUserStore()
|
|
|
|
if (to.meta.requiresAuth && !store.isLoggedIn) {
|
|
return '/login'
|
|
}
|
|
})
|
|
```
|
|
|
|
## SSR Applications
|
|
|
|
Always pass the `pinia` instance to `useStore()`:
|
|
|
|
```ts
|
|
const pinia = createPinia()
|
|
const app = createApp(App)
|
|
app.use(router)
|
|
app.use(pinia)
|
|
|
|
router.beforeEach((to) => {
|
|
// ✅ Pass pinia instance
|
|
const main = useMainStore(pinia)
|
|
|
|
if (to.meta.requiresAuth && !main.isLoggedIn) {
|
|
return '/login'
|
|
}
|
|
})
|
|
```
|
|
|
|
## serverPrefetch()
|
|
|
|
Access pinia via `this.$pinia`:
|
|
|
|
```ts
|
|
export default {
|
|
serverPrefetch() {
|
|
const store = useStore(this.$pinia)
|
|
return store.fetchData()
|
|
},
|
|
}
|
|
```
|
|
|
|
## onServerPrefetch()
|
|
|
|
Works normally in `<script setup>`:
|
|
|
|
```vue
|
|
<script setup>
|
|
const store = useStore()
|
|
|
|
onServerPrefetch(async () => {
|
|
// ✅ Just works
|
|
await store.fetchData()
|
|
})
|
|
</script>
|
|
```
|
|
|
|
## Key Takeaway
|
|
|
|
Defer `useStore()` calls to functions that run after pinia is installed, rather than calling at module scope.
|
|
|
|
<!--
|
|
Source references:
|
|
- https://pinia.vuejs.org/core-concepts/outside-component-usage.html
|
|
-->
|