Skip to content

Commit

Permalink
fix: throw when a store is used outside of a Nuxt-aware context. (POC)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pguilbert committed Dec 11, 2024
1 parent 2071db2 commit 2a0c9ed
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 0 deletions.
17 changes: 17 additions & 0 deletions packages/nuxt/playground/pages/usage-after-await.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts" setup>
const useFancyCounter = async () => {
await new Promise((resolve) => setTimeout(resolve, 0))
// ❌ bad usage: the use of a store after an await could lead to using the wrong pinia instance.
return useCounter()
}
const counter = await useFancyCounter()
</script>

<template>
<div>
<p>Count: {{ counter.$state.count }}</p>
<button @click="counter.increment()">+</button>
</div>
</template>
23 changes: 23 additions & 0 deletions packages/nuxt/src/runtime/composables.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
import { useNuxtApp } from '#app'
import {
defineStore as _defineStore,
type Pinia,
type StoreGeneric,
} from 'pinia'
export * from 'pinia'

export const usePinia = () => useNuxtApp().$pinia

export const defineStore = (...args) => {
if (!import.meta.server) {
return _defineStore(...args)
}

const store = _defineStore(...args)

function useStore(pinia?: Pinia | null, hot?: StoreGeneric): StoreGeneric {
if (pinia) {
return store(pinia, hot)
}

return store(usePinia(), hot)
}

return useStore
}
4 changes: 4 additions & 0 deletions packages/nuxt/test/nuxt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ describe('works with nuxt', async () => {
expect(html).not.toContain('I should not be serialized or hydrated')
expect(html).toContain('skipHydrate-wrapped state is correct')
})

it('throws an error server-side when the nuxt context is not available', async () => {
await expect($fetch('/usage-after-await')).rejects.toThrow()
})
})

0 comments on commit 2a0c9ed

Please sign in to comment.