Skip to content

Commit 2a0c9ed

Browse files
committed
fix: throw when a store is used outside of a Nuxt-aware context. (POC)
Prefer the Nuxt Pinia instance over the global active Pinia instance. Since the Nuxt Pinia instance is discarded after each request, it ensures that we can't accidentally use one from another request. Additionally, `usePinia` will throw an error when used outside of a Nuxt-aware context. The error is as follows in dev : > [nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function.
1 parent 2071db2 commit 2a0c9ed

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script lang="ts" setup>
2+
const useFancyCounter = async () => {
3+
await new Promise((resolve) => setTimeout(resolve, 0))
4+
5+
// ❌ bad usage: the use of a store after an await could lead to using the wrong pinia instance.
6+
return useCounter()
7+
}
8+
9+
const counter = await useFancyCounter()
10+
</script>
11+
12+
<template>
13+
<div>
14+
<p>Count: {{ counter.$state.count }}</p>
15+
<button @click="counter.increment()">+</button>
16+
</div>
17+
</template>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
11
import { useNuxtApp } from '#app'
2+
import {
3+
defineStore as _defineStore,
4+
type Pinia,
5+
type StoreGeneric,
6+
} from 'pinia'
27
export * from 'pinia'
38

49
export const usePinia = () => useNuxtApp().$pinia
10+
11+
export const defineStore = (...args) => {
12+
if (!import.meta.server) {
13+
return _defineStore(...args)
14+
}
15+
16+
const store = _defineStore(...args)
17+
18+
function useStore(pinia?: Pinia | null, hot?: StoreGeneric): StoreGeneric {
19+
if (pinia) {
20+
return store(pinia, hot)
21+
}
22+
23+
return store(usePinia(), hot)
24+
}
25+
26+
return useStore
27+
}

packages/nuxt/test/nuxt.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@ describe('works with nuxt', async () => {
3333
expect(html).not.toContain('I should not be serialized or hydrated')
3434
expect(html).toContain('skipHydrate-wrapped state is correct')
3535
})
36+
37+
it('throws an error server-side when the nuxt context is not available', async () => {
38+
await expect($fetch('/usage-after-await')).rejects.toThrow()
39+
})
3640
})

0 commit comments

Comments
 (0)