Search code examples
javascriptvue.jsvuejs3pinia

Access pinia store from routes file


I am building a breadcrumbs component with Vue 3, Vue Router, and Pinia. I use a breadcrumbs meta key on my routes with a label and parent attribute. The component generates an array by resolving the parent routes recursively using router.resolve() and then create the component markup from this array. I use a pinia store and I want to dynamically generate the meta.label property on my routes file using attributes stored in the pinia store.

If I import the pinia store on the routes file like this:

// routes file
import { useRentalStore } from "@/stores/rentalStore";

const rentalStore = useRentalStore();

const routes = [
  // extract from routes array
  {
    path: ":equipment",
    name: "rental-show",
    component: ShowRentalView,
    meta: {
      breadcrumbs: {
        label: () => rentalStore.rental.label,
        parent: "rental-index",
      },
    },
  },
];

I get the following error: "getActivePinia()" was called but there was no active Pinia. Did you forget to install pinia? const pinia = createPinia()

I tried passing the pinia instance from the main entrypoint main.js

// main.js
const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.use(router)
//...
export { pinia }

// routes file
import {pinia} from '@/main.js'

const rentalStore = useRentalStore(pinia);

But this still won't work. I used a similar approach in Vue 2 with Vuex and the above worked with Vuex but it is not working with Pinia.. The above returns the following error message: Cannot access 'pinia' before initialization.

Any idea how to access the pinia store from the routes file? The pinia docs recommend to defer calls of useStore() by placing them inside functions that will always run after pinia is installed, but the parent route component will not run when the child component navigation is active.


Solution

  • Pinia creates store functions instead of store instances in order to avoid early instantiation. When used outside a component, useRentalStore should be called in a place where a store is used:

    ...
    label: () => useRentalStore().rental.label,
    ...