Search code examples
vue.jsvue-componentvuexvuejs3vue-composition-api

Vue 3: How to access state in a method function


New to Vue so may be missing a basic part of Vuex or more likely how the composition API works. I am trying to make a POST request to my API. I don't want to store the User's Id in session storage, instead I want to retrieve it from my store. I can't seem to pass my computed retrieval of the state value to my async API method call. It is logged as undefined, my user in the state is populated after they login or register. Guidance appreciated!

Composition API Script Tag for Component

export default {
  name: 'ModalContent',
  setup() {
    const store = useStore();
    const uid = computed(() => store.state.user.data.id);
    const loading = ref(true);
  },
    data() {
    return {
      session_name: "",
      dated: "",
      time_est: 60,
    };
  },
  methods: {
    async newSession() {
      const { session_name, dated, time_est, uid } = this;
      console.log(uid) ***UNDEFINED***     
      // const res = await fetch(
      //   "https://www...",
      
    }

Vuex Store

const store = createStore({
    state: {
        status: '',
        user: {},
        token: sessionStorage.getItem('TOKEN'),
    },
    getters: {},
    actions: {
        storeUserData({commit}, data) {
            commit('setUser', data.user);
            commit('setToken', data.token)
            },
    },

Solution

  • Your setup function has to expose whatever you want to be available on the component instance, by returning an object:

    setup() {
      const store = useStore();
      const uid = computed(() => store.state.user.data.id);
      const loading = ref(true);
      return { loading, uid }
    },
    

    Now this.loading and this.uid will work in any method, and they're both accessible in the template (as loading and uid).


    However, the proper way of doing this would be to move the method inside setup function (define it as a const), along these lines:

    setup() {
      const store = useStore();
      const uid = computed(() => store.state.user.data.id);
      const loading = ref(true);
      const newSession = async () => {
        return await //... call your API
      }        
      return { loading, uid, newSession }
    },
    

    If the template needs it, you add it to the returned object from setup.
    If not, there's no need to expose it.

    Ideally, when you're done refactoring, all members of methods, computed, watch, any hooks (e.g: mounted, beforeDestroy), should have been moved inside setup.