Search code examples
typescriptvue.jsvuejs3vue-composition-apivuex4

Vuejs 3 - How to send data to template from other hooks than data() and setup()?


I'm somewhat new to Vue/VueX so there sure must be something I don't understand right.

I have a very simple component:

  • It fetches a collection of items from VueX mapState (in computed())
  • In which I fetch a single item from (in mounted() at the moment)
  • I then need to push that item to the template but I can't figure it out

The way I understand, we can only push data to template from setup or data methods but not from mounted, created hooks, etc. Does this sound right?

In the following example code, how could I send the item object I get from items in mounted() to the template?

I cannot do it all in setup since my computed() VueX items object isn't available yet in there. Any suggestion about how to correctly achieve this simple goal?

<template>
  <p>ID: {{ id }}</p>
  <p>Name:: {{ item.name }}</p>
</template>

<script lang="ts">
import { useRoute } from 'vue-router'
import { ref, computed, watch } from 'vue'
import { mapState, mapActions } from 'vuex'

export default {
  // fetching items from vuex (works)
  computed: mapState({
    items: (state: any) => state.items
  }),
  setup() {
    const route = useRoute()
    // parsing ID from route params (works)
    const id = ref(route.params.id || 'Plants')
    return {
      id,
      // this seems to be the proper way of pushing data to template:
      // item: { name: 'this works from here' }
    }
  },
  mounted() {
    // fetch item by id (works)
    const item: Plant = this.items.find(i => i.id === this.id)

    // TODO: I need to push this to the template but I cannot from here
    return { item }
  }
}
</script>

Solution

  • The best way for this case to define another computed property like :

    export default {
     
      computed:{ ...mapState({//should spread the mapState in order to add other properties
        items: (state: any) => state.items
      }),
      item(){
        const _item: Plant = this.items.find(i => i.id === this.id)
        return  _item;
       }
    
     },
      setup() {
        const route = useRoute()
        // parsing ID from route params (works)
        const id = ref(route.params.id || 'Plants')
        return {
          id,
         
        }
      },
    
    }
    

    or use purely the options api :

    export default {
     
      computed:{ ...mapState({//should spread the mapState in order to add other properties
        items: (state: any) => state.items
      }),
      item(){
        let id=this.$route.params.id || 'Plants'
        const _item: Plant = this.items.find(i => i.id === id)
        return  _item;
       }
    
     },
    
    }
    

    and

    <template>
      <p>ID: {{ $route.params.id }}</p>
      <p>Name:: {{ item.name }}</p>
    </template>