Search code examples
javascriptvue.jsvuexpinia

Dynamic getters in pinia - Vue 3


There is code for Vue 2 with Vuex 3.4:

getLink: (state, getters) => rel => {
  let link = state.data?.getLinkWithRel(rel);
  let stac = getters[rel];
  let title = STAC.getDisplayTitle([stac, link]);
  if (link) {
    link = Object.assign({}, link);
    link.title = title;
  }
  else if (stac instanceof STAC) {
    return {
      href: stac.getAbsoluteUrl(),
      title,
      rel
    };
  }
  return link;
},

This code should be ported to Vue 3 with pinia. Did the following:

getLink: (state) => (rel) => {
  let link = state.data?.getLinkWithRel(rel);
  let stac = state[rel];
  let title = STAC.getDisplayTitle([stac, link]);

  if (link) {
    link = { ...link };
    link.title = title;
  }
  else if (stac instanceof STAC) {
    return {
      href: stac.getAbsoluteUrl(),
      title,
      rel
    };
  }

  return link;
},

The stac variable contains either null or undefined values.

When using version 1, stac contains the data returned by the called getters[rel] function.

How do I write or force pinia to give data?

Additional information:

rel - contains a string with one of the getter names (parent or collection).

getter-parent:

parent: (state) => state.getStacFromLink('parent'),

Where getStacFromLink is also a getter.

getter-collection:

collection: (state) => state.getStacFromLink('collection'),

It looks like the parent or collection getters that are called do not get the state of the Store.


Solution

  • You solution seems a bit over complicated to me.

    If both getters parent and collection just call getStacFromLink with hardcoded rel, then why not simply

    let stac = state.getStacFromLink(rel);
    

    I haven't found a way to access getters dynamically in Pinia. And I think it's is good so. Consider to overthink your getters and store design.

    const { createApp, ref } = Vue
    const { createPinia, defineStore, storeToRefs } = Pinia
    
    const Store = defineStore('test',
    {
        state: () => {
          return { data: 
            {
              getLinkWithRel: (rel) => {
                 return { href: rel, title: rel }
              }
            }
          }
        },
        getters: {
          parent: (state) => state.getStacFromLink('parent'),
          getStacFromLink: (state) => (rel) => {
            return { stac: rel }
          },      
          getLink: (state, getters) => (rel) => {
            let link = state.data?.getLinkWithRel(rel);
            console.log(link);
            let stac = state.getStacFromLink(rel);
            console.log(stac);             
            return link;
          }
        }
      }
    )
    
    const App = {
      setup() {
        const store = Store()
        const refs = storeToRefs(store)
        return {
          store, refs
        }
      }
    }
    
    const app = createApp(App)
    const pinia = createPinia()
    app.use(pinia)
    app.mount('#app')
    #app { line-height: 1.75; }
    [v-cloak] { display: none; }
    <div id="app">
    getLink('parent'):  {{ store.getLink('parent') }}<br/>
    getLink('collection'):  {{ store.getLink('collection') }}<br/>
    refs['parent']: {{ refs['parent'] }}
    </div>
    <script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
    <script src="https://unpkg.com/[email protected]/lib/index.iife.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/pinia.iife.js"></script>