javascript - Access pinia store from routes file - Stack Overflow

I am building a breadcrumbs ponent with Vue 3, Vue Router, and Pinia. I use a breadcrumbs meta key on m

I am building a breadcrumbs ponent with Vue 3, Vue Router, and Pinia. I use a breadcrumbs meta key on my routes with a label and parent attribute. The ponent generates an array by resolving the parent routes recursively using router.resolve() and then create the ponent 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",
    ponent: 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 remend to defer calls of useStore() by placing them inside functions that will always run after pinia is installed, but the parent route ponent will not run when the child ponent navigation is active.

I am building a breadcrumbs ponent with Vue 3, Vue Router, and Pinia. I use a breadcrumbs meta key on my routes with a label and parent attribute. The ponent generates an array by resolving the parent routes recursively using router.resolve() and then create the ponent 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",
    ponent: 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 remend to defer calls of useStore() by placing them inside functions that will always run after pinia is installed, but the parent route ponent will not run when the child ponent navigation is active.

Share Improve this question edited Oct 19, 2023 at 2:35 Darryl Noakes 2,8201 gold badge14 silver badges30 bronze badges asked Sep 6, 2023 at 15:38 enriqg9enriqg9 1,5071 gold badge22 silver badges42 bronze badges 2
  • You need to have created the pinia object before initializing the router. Otherwise it's a bit of a circular dependency of the main file importing the router, which imports the main file... I use a separate file for it, in my stores directory. Should I write up a full answer? – Darryl Noakes Commented Sep 6, 2023 at 15:45
  • @DarrylNoakes yes if you don't mind please. I also tried to pute the label inside the showRentalView ponent and exposing the puted property to the routes file but that didn't seem to work either. – enriqg9 Commented Sep 6, 2023 at 15:55
Add a ment  | 

2 Answers 2

Reset to default 4

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

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

Notice: use the approach from the section at the end instead of actually using this approach. It is for explanation only, and should only be used when there is no other/better way.

You need to have created the pinia object before initializing the router. Otherwise there's a bit of a circular dependency of the main file importing the router, which imports the main file...

The solution is to use a separate file for initializing Pinia, and import that. The best is probably as the index file of the stores directory. For example, use this as stores/index.js:

import { createPinia } from "pinia";

const pinia = createPinia();

export default pinia;

(This also provides a contained location to apply Pinia plugins, if you use any.)

Then, in your router file, import the Pinia instance from this and pass it to the store function:

import pinia from "@/stores";
import { useRentalStore } from "@/stores/rentalStore";

const rentalStore = useRentalStore(pinia);

// As before...

And, in your main file, import the Pinia instance and use that:

// ...

import pinia from "@/stores";

const app = createApp(App)

app.use(pinia)
app.use(router)

Usually, this is an anti-pattern.

The better choice is to "use" the store where it is used.
For example:

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

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

As long as the store function is called after the Pinia instance has been installed with app.use(pinia), Pinia will automatically use that instance; it only needs to be passed in if the store function is called before the Pinia instance is installed.

The docs have a short section on this: Using a store outside of a ponent | Pinia.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745362365a4624417.html

相关推荐

  • javascript - Access pinia store from routes file - Stack Overflow

    I am building a breadcrumbs ponent with Vue 3, Vue Router, and Pinia. I use a breadcrumbs meta key on m

    4小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信