0

Please bare with me I am still new to using Vuex and don't quite understand it yet. I am using Vuex4 with localforage package for IndexedDB.

My Vuex store is as follows:

import { createStore } from 'vuex'
import localforage from 'localforage'
import axios from 'axios'

const store = createStore({
  state: {
    tenantLocale: {}
  },
  getters: {},
  mutations: {
    setLocale(state, value) {
      state.tenantLocale = value
    }
  },
  actions: {
    getTenant(context) {
      axios.get('/api/tenant-data/locale').then((response) => {
        context.commit('setLocale', response.data)
        localforage.setItem('tenantLocale', response.data)
      })
    }
  }
})

export default store

I dispatch the action in my App.vue like this:

import { useStore } from 'vuex'

export default {
  setup() {
    const store = useStore()

    //get default information about tenant from api
    store.dispatch('getTenant')

    return {}
  }
}

The thing is now if I render the state in my Login.vue component in the template section like so:

<h1>{{ store.state.tenantLocale.timezone }}</h1>

It shows the correct data, but if I try to do something with it in the script section of my component lets say for example try to print it out:

console.log(store.state.tenantLocale.timezone)

I get the undefined message.

What am I missing here? What would be the best approach here? Do I need to create getter for it? Create a promise? My brain is fried... Any help to at least point me in the right direction is appreciated!

Fersek
  • 37
  • 1
  • 6
  • "but if I try to do something with it in the script section of my component" - where exactly? The operation is asynchronous. You can't get a result synchronously. It's a mistake to put asynchronous side effects just into setup, should be either inside onMounted, or the whole component needs to be async. – Estus Flask Jan 06 '22 at 20:02
  • I get what you mean but I tried putting it inside onMounted I still get undefined result that's why im so confused – Fersek Jan 07 '22 at 08:36
  • 1
    What exactly do you do in onMounted? You can't expect it to be defined until asynchronous operation is complete. If it's done with getTenant action then typically you have to wait for a promise. "Create a promise? " - there's already a promise from `dispatch` which you ignored. If you're not sure what's going on there you can also check https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call – Estus Flask Jan 07 '22 at 09:10
  • For example if I wanted to create a date that takes values based on the tenantLocale object: ```date = new Date().toLocaleString(store.state.tenantLocale.localization, { timeZone: `${store.state.tenantLocale.timezone}` })``` – Fersek Jan 07 '22 at 09:24
  • 1
    `date` should be a computed, as the answer suggests. If the value is undefined at the time when you access `date` this means that you need to postpone its access somehow until all relevant data is available. There are several uniform ways to do this in Vue. It depends on your case which one is preferable. You could move dispatch('getTenant') to a parent and not render a child until data is available, or use Vue 3's Suspense – Estus Flask Jan 07 '22 at 09:43

2 Answers2

0

In setup function you access state or getter with computed :

computed(() => store.state.tenantLocale.timezone)
Nikola Pavicevic
  • 21,952
  • 9
  • 25
  • 46
0

You can do like this

import { computed } from 'vue'
import { useStore } from 'vuex'

export default {
  setup () {
    const store = useStore()

    return {
      // access a state in computed function
      timezone: computed(() => store.state.tenantLocale.timezone),

    }
  }
}
  • I am using the composition API so I can't use this keyword. – Fersek Jan 06 '22 at 19:57
  • In that case do like this import { computed } from 'vue' import { useStore } from 'vuex' export default { setup () { const store = useStore() return { // access a state in computed function timezone: computed(() => store.state.tenantLocale.timezone), } } } – Faisal Nadeem Jan 06 '22 at 20:03