'How to pass an argument to Pinia store?

I'm making a session API call in main.js and using values from the response as the initial value for my root store. In vuex it's handled this like,

DataService.getSession()
  .then((sessionData) => {
    new Vue({
      i18n,
      router,
      // this params sessionData.session will be passed to my root store
      store: store(sessionData.session),
      render: (h) => h(App),
    }).$mount('#app');
  })

Consumed like,

export default function store(sessionData) { // here I'm getting the sessionData
  return new Vuex.Store({
    strict: process.env.NODE_ENV !== 'production',
    state: {
      // some states here
    },
  });
}

In case of Pinia we're creating a app instance & making it use like, app.use(createPinia())

And my store would be like,

// how to get that sessionData here
import { defineStore } from 'pinia'

export const useCounterStore = defineStore({
  id: 'counter',
  state: () => ({
    counter: 0
  })
})

Is it possible to pass the sessionData someway to the pinia store?



Solution 1:[1]

You could cache the session data in your store, and initialize the store's data with that:

  1. In your store, export a function that receives the session data as an argument and returns createPinia() (a Vue plugin). Cache the session data in a module variable to be used later when defining the store.

  2. Define a store that initializes its state to the session data cached above.

  3. In main.js, pass the session data to the function created in step 1, and install the plugin with app.use().

// store.js
import { createPinia, defineStore } from 'pinia'

1??
let initData = null

export const createStore = initStoreData => {
  initData = { ...initStoreData }
  return createPinia()
}

export const useUserStore = defineStore('users', {
  state: () => initData, 2??
})
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import { createStore } from './store'
import * as DataService from './data-service'

DataService.getSession().then(sessionData => {
  createApp(App)
    .use(createStore(sessionData)) 3??
    .mount('#app')
})

demo

Solution 2:[2]

When you create a store in Pinia using defineStore() you give it the initial state. So wherever you do that just pass the data into it and then do

defineStore('name', {
    state: () => {
        isAdmin: session.isAdmin,
        someConstant: 17
    },
    actions: { ... }
});

Solution 3:[3]

There are 3 ways to pass parameters to a Pinia store - see the list below. You could use either #2 or #3 .

In most cases it is wise to initialise your Vue instance and show the user something while they are waiting for connections to resolve. So you may find it simpler to just access or initialise the store by calling DataService.getSession() in say a "SessionStore" action which can be async. Typically Components =access=> Stores =access=> Services.

Unlike Vuex, you don't need a root Pinia store. You can get just call useSomeStore() in the setup method for any component. Each store can just be an island of data.

1. Pass common params to every action.

export const useStore = defineStore('store1', {
  state: () => ({
    ...
  }),
  actions: {
    action1(param1: string ... ) {
      // use param1
    }    
  }
});

2. Initialise store AFTER creating it

Only works if there's one instance of this store required

export const useStepStore = defineStore('store2', {
  state: () => ({
    param1: undefined | String,
    param2: undefined | String,
    ...
  }),
  getters: {
    geStuff() { return this.param1 + this.param2; } 
  } 
  actions: {
    init(param1: string, param2: string) {
      this.param1 = param1
      this.param2 = param2
    },
    doStuff() {
      // use this.param1
    }    
  }
});

3. Factory pattern to dynamically create store instances

export function useStore(storeId: string, param1: string ...) {
  return defineStore(storeId, () => {
    // Use param1 anywhere
  })()
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tony19
Solution 2 Sami Kuhmonen
Solution 3