Search code examples
typescriptvue.jsvuejs3pinia

How to properly use Pinia store in root vue component?


My main.ts:

import './assets/tailwind.css'
import './assets/wordpress.css'

import { createApp } from 'vue'
import { createPinia } from 'pinia'

import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(createPinia())
app.use(router)

app.mount('#app')

And I'm trying to use a store in App.vue:

<script setup lang="ts">
import NavigationBar from '@/components/navigation/NavigationBar.vue'
import TopBar from '@/components/header/TopBar.vue'
import NavigationDrawer from '@/components/navigation/NavigationDrawer.vue'
import { onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import ErrorSnackbar from '@/components/ErrorSnackbar.vue'
import { useUser } from '@/stores/user'

const router = useRouter();
const route = useRoute()

onMounted(() => {
  const user = useUser()
  user.signInSilent()
});
</script>

But I'm getting following error:

Uncaught Error: [🍍]: "getActivePinia()" was called but there was no active Pinia. Are you trying to use a store before calling "app.use(pinia)"?
See https://pinia.vuejs.org/core-concepts/outside-component-usage.html for help.
This will fail in production.
    useStore pinia.mjs:1709
    <anonymous> user.ts:9
pinia.mjs:1709:18
    useStore pinia.mjs:1709
    <anonymous> user.ts:9

I don't understand this. Even with setActivePinia it still does not work. And the app is mounted at the end of main.ts. So why does it not work and how can I fix it?


Solution

  • The issue has to do with something else, unrelated to App.vue itself.

    In the user store I was using another store:

    import { defineStore } from 'pinia'
    import { useErrors } from '@/stores/errors'
    
    const errors = useErrors()
    
    export const useUser = defineStore('user', () => {
      const currentLoginToken = ref<string | null>(null)
      // ...
    })
    

    The problem is that const errors = useErrors() is in the root level and thus already executed at import time which is before anything else runs in App.vue and since main.ts imports App.vue, it also runs before anything in main.ts runs and thus causes the error.

    main.ts ---- imports ----> App.vue ---- imports ----> user.ts ---- uses ----> useErrors()

    And useErrors() would run before app.use(createPinia()). So to solve this, move the line to inside the store:

    import { defineStore } from 'pinia'
    import { useErrors } from '@/stores/errors'
    
    export const useUser = defineStore('user', () => {
      const errors = useErrors()
      const currentLoginToken = ref<string | null>(null)
      // ...
    })