How to get vuex state from a javascript file (instead of a vue component)

37,338

Solution 1

It is possible to access the store as an object in an external js file, I have also added a test to demonstrate the changes in the state.

here is the external js file:

import { store } from '../store/store'

export function getAuth () {
  return store.state.authorization.AUTH_STATE
}

The state module:

import * as NameSpace from '../NameSpace'
/*
   Import everything in NameSpace.js as an object.
   call that object NameSpace.
   NameSpace exports const strings.
*/

import { ParseService } from '../../Services/parse'

const state = {
  [NameSpace.AUTH_STATE]: {
    auth: {},
    error: null
  }
}

const getters = {
  [NameSpace.AUTH_GETTER]: state => {
    return state[NameSpace.AUTH_STATE]
  }
}

const mutations = {
  [NameSpace.AUTH_MUTATION]: (state, payload) => {
    state[NameSpace.AUTH_STATE] = payload
  }
}

const actions = {
  [NameSpace.ASYNC_AUTH_ACTION]: ({ commit }, payload) => {
    ParseService.login(payload.username, payload.password)
      .then((user) => {
        commit(NameSpace.AUTH_MUTATION, {auth: user, error: null})
      })
      .catch((error) => {
        commit(NameSpace.AUTH_MUTATION, {auth: [], error: error})
      })
  }

export default {
  state,
  getters,
  mutations,
  actions
}

The store:

import Vue from 'vue'
import Vuex from 'vuex'
import authorization from './modules/authorization'

Vue.use(Vuex)

export const store = new Vuex.Store({
  modules: {         
    authorization    
  }                  
})                   

So far all I have done is create a js file which exports a function returning the AUTH_STATE property of authorization state variable.

A component for testing:

<template lang="html">
    <label class="login-label" for="username">Username
        <input class="login-input-field" type="text" name="username" v-model="username">
    </label>
    <label class="login-label" for="password" style="margin-top">Password
         <input class="login-input-field" type="password" name="username" v-model="password">
    </label>
    <button class="login-submit-btn primary-green-bg" type="button" @click="login(username, password)">Login</button>
</template>

<script>
import { mapActions, mapGetters } from 'vuex'
import * as NameSpace from '../../store/NameSpace'
import { getAuth } from '../../Services/test'

export default {
  data () {
    return {
      username: '',
      password: ''
    }
  },
  computed: {
    ...mapGetters({
      authStateObject: NameSpace.AUTH_GETTER
    }),
    authState () {
      return this.authStateObject.auth
    },
    authError () {
      return this.authStateObject.error
    }
  },
  watch: {
    authError () {
        console.log('watch: ', getAuth()) // ------------------------- [3]
      }
    },
    authState () {
      if (this.authState.sessionToken) {
        console.log('watch: ', getAuth()) // ------------------------- [2]
      }
    },
  methods: {
    ...mapActions({
      authorize: NameSpace.ASYNC_AUTH_ACTION
    }),
    login (username, password) {
      this.authorize({username, password})
      console.log(getAuth())             // ---------------------------[1]
    }
  }
}
</script>

On the button click default state is logged on to the console. The action in my case results in an api call, resulting a state change if the username - password combination had a record.

A success case results in showing the console in authState watch, the imported function can print the changes made to the state.

Likewise, on a fail case, the watch on authError will show the changes made to the state

Solution 2

For anyone wondering how to access a mutation from a javascript file, you can do the following:

import store from './store'
store.commit('mutation_name', mutation_argument);

Or for actions,

store.dispatch('action_name', action_argument)

Solution 3

import store from './store'

and than

store.commit('mutation_name', mutation_argument)

if you use js file

Solution 4

You can also access actions like:

import store from './store'
store.dispatch('action_name', action_argument)
Share:
37,338
musicformellons
Author by

musicformellons

Updated on July 09, 2022

Comments

  • musicformellons
    musicformellons almost 2 years

    I am working with vuex (2.1.1) and get things working within vue single file components. However to avoid too much cruft in my vue single file component I moved some functions to a utils.js module which I import into the vue-file. In this utils.js I would like to read the vuex state. How can I do that? As it seems approaching the state with getters etc is presuming you are working from within a vue component, or not?

    I tried to import state from '../store/modules/myvuexmodule' and then refer to state.mystateproperty but it always gives 'undefined', whereas in the vue-devtools I can see the state property does have proper values.

    My estimate at this point is that this is simply not 'the way to go' as the state.property value within the js file will not be reactive and thus will not update or something, but maybe someone can confirm/ prove me wrong.