Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

238
Visualizações
Do I need to import Pinia store props multiple times in a Vue component?

I am working on my first Vue project. I'm used to React and vanilla js, but just getting my head around a few concepts in Vue here.

In particular, importing state and action props from a Pinia store, and seemingly having to import those multiple times in a single Vue component (something I don't need to do in React).

In this example, I am importing a simple count value, and an increment function, and trying to use these in a few different places:

<script setup>
// I import everything initially in setup, which works fine,
// and these props (currentCount and incrementCount)
// can be used in my template:
import { storeToRefs } from 'pinia';
import { useStore } from '@/stores/store';
const { currentCount } = storeToRefs(useStore());
const { incrementCount } = useStore();
</script>

<template>
  <main>
    Current count: {{ currentCount }}
    <button @click="incrementCount">Increment</button>
  </main>
</template>

<script>
// I can't use store values from setup here.
// This doesn't work:
// console.log(currentCount);

// I also can't import store values here.
// I get the following error:
// "getActivePinia was called with no active Pinia"
// const { currentCount } = storeToRefs(useStore());

export default {
  mounted() {
    // I have to import store values here for them to work:
    const { currentCount } = storeToRefs(useStore());
    console.log(currentCount);
  },
  watch: {
    // weirdly, this reference to watching "currentCount" works:
    currentCount() {
      // I also have to import store values here for them to work:
      const { currentCount } = storeToRefs(useStore());
      console.log(currentCount);
    },
  },
};
</script>

As you can see, if I want to use store values in my template, on mount, and in a watcher (whereby I'd use React's useEffect hook) I am having to import the store props 3 times in total.

Is this correct / normal? Is there a simpler way to achieve what I'm doing, where I only import props once? I want to be sure I haven't missed something and am not doing something in an unusual way.

Thanks for any help and advice!

about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

Pinia was designed with Composition API in mind.
So its intended usage is inside setup() function, where you'd only import it once.

To use it outside of a setup() function, you have two main routes:

  • inside components, you can just return it from setup() and it becomes available in any hook/method/getter. Either as this.store or spread:
import { useStore } from '@/store'
import { toRefs } from 'vue'
            // or from '@vue/composition-api' in Vue2

export default {
  setup: () => ({ ...toRefs(useStore()) })
}
/* this makes every state prop, getter or action directly available 
   on current component instance. In your case, `this.currentCount`.
   Obviously, you can also make the entire store available as `this.someStore`:

  setup: () => ({ someStore: useSomeStore() })
  // now you can use `this.someStore` anywhere 
 */
  • a more general approach is to export the pinia instance (returned by createPinia()), from main.(js|ts), import it where you need the store and then call useStore() passing the pinia instance as an argument.
    This can be done anywhere, even outside of components.
    Generic example:
import { pinia } from 'main.js'
import { useSomeStore } from '@/store'

const someStore = useSomeStore(pinia);

I should probably also mention the mapState helper provided by pinia. It allows you to select only a few of the keys exposed to current instance. Example:

import { mapState } from 'pinia'
// ...
   computed: {
    ...mapState(useSomeStore, [ 'currentCount'])
  }
// Now `this.currentCount` is available

Note: mapState is weirdly named, as it allows you to access more than just state props (also getters and actions). It was named mapState to match the similar helper from vuex.


An even more general approach is to add your store as global, using the plugin registration API in Vue2:

import { useSomeStore } from '@/store';
import { createPinia } from 'pinia';

const pinia = createPinia();

const someStorePlugin = {
  install(Vue, options) {
    Vue.prototype.someStore = useSomeStore(options.pinia)
  }
};

Vue.use(someStorePlugin, { pinia });

new Vue({ pinia });

After this, every single component of your Vue instance will have this.someStore available on it, without you needing to import it.

Note: I haven't tested adding a store in globals (and I definitely advise against it - you should avoid globals), but i expect it to work.

about 4 years ago · Juan Pablo Isaza Relatório

0

If you want to combine pinia stores with the options API, one way to do it is to use the setup() function inside the options to call useStore:

<script>
import { useStore } from '@/stores/store';

export default {
  setup() { 
    const store = useStore();
    return {store}
  },
  watch: {
    store.currentBrightness(newVal, oldVal){
      // your code
    }
  },
  methods: {
   // inside methods use this.store
  },
  mounted() {
    console.log(this.store.currentCount);
  }
}
</script>

Some might consider this as a unwanted mix of composition and options API, but in my view it is a quite good solution for pinia stores.

about 4 years ago · Juan Pablo Isaza Relatório

0

Nechoj, has the most straightforward answer. Also if you have multiple stores you can always import the stores as necessary into a parent component then use inject just add some parts. For example I have a route data that is called via an api, I don't need it everywhere all the time so i call it in a parent then use inject to use those routes in a drop down that might be a great grandchild component. I don't need that whole utils store just the routes. index page:

import { useUtilsStore } from "src/stores/utilsStore";
const passengerRoutes = computed(() => utilsStore.getPassengerRoutes);
provide("passengerRoutes", passengerRoutes);

grandchild component:

const compRoutes = inject("passengerRoutes");
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda