docs: add advanced skills for Vitest, Pinia, and Vue built-ins
Add comprehensive reference documentation for: - Vitest: environments, projects/workspaces, type testing, vi utilities - Pinia: HMR, Nuxt integration, SSR setup - Vue: built-in components (Transition, Teleport, Suspense, KeepAlive) and advanced directives
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
---
|
||||
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
|
||||
-->
|
||||
Reference in New Issue
Block a user