Search code examples
vue-componentvuejs3pinia

Re render in Vue3 - how to update component when store value changes


I am using the pinia store and I need to update a component in realtime. The variable num1 will be changing value from another component and I need to display the change in this component:

<template>
  <div>
    <p>{{ num1 }}</p>
  </div>
</template>

<script>
import { useCalcStore } from '@/store/store'

export default {
  name: 'screenCalculator',

  setup(){
    const store = useCalcStore();
    

    const reload = () => {
      let num1 = store.getNumber1;
      return num1
    }
    return {reload}
  }
}
</script>

I have tried to use the keys and forceUpdate but I haven't succeeded.


Solution

  • Reading from a store should not be done in a reload function.
    The whole point of using stores is: they hold reactive data in state or getters (derived state), shared across all components importing them.

    Whenever this data changes, all components receive the change, and update automatically.

    In a nutshell, that's what reactivity means: realtime self-updating data.


    Your current syntax:

    let num1 = store.getNumber1 // ❌ not reactive
    

    ...breaks reactivity, while using any of the following alternative syntaxes maintains it:

    const num1 = storeToRefs(store).getNumber1 // ✅ reactive 
    
    const { getNumber1: num1 } = storeToRefs(store) // ✅ reactive 
    
    const num1 = computed(() => store.getNumber1) // ✅ reactive 
    
    

    num1 is now a ref() which can be used in template and will reflect any change in store.getNumber1's value.
    If you need its value inside <script>, use num1.value, like with any other ref.


    Complete example (I skipped creating consts for store and num1, since they're only used once, but setup does return a num1 ref for <template>, pointing to store.getNumber1):

    <template>
      <p>{{ num1 }}</p>
    </template>
    
    <script>
    import { useCalcStore } from '@/store/store'
    import { storeToRefs } from 'pinia'
    
    export default {
      name: 'screenCalculator',
      setup: () => ({
        num1: storeToRefs(useCalcStore()).getNumber1
      })
    }
    </script>
    

    Important note: storeToRefs only returns reactive store members (state and getters).
    actions can be obtained from the store itself:

    const { action1, action2 } = useSomeStore()