29
votes

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.

4
I dont fully understand as I cant see your files but vue.use(vuex) adds up vuex to all your vue components. Which could be a reason why your utils.js would not have access to it. I let external functions to be a part of actions, which take state as arguments and return the value for mutation.Amresh Venugopal
There are no demo files as it is a 'general issue'. And yes, I do know how to solve this within a vue-file, but my question is 'how to get state in a js file'. Your 'solution' is not clear to me; it seems you are just approaching the state within the vue-file (using 'external functions'). However, I want to (if possible) approach vue state from within a js file.musicformellons
Yes, I prefer to not alter the state externally. Can you give an idea of what kind of work you are doing in utils? Because I strongly feel using vuex actions or mutations would eliminate the need to get state outside the vuex store.Amresh Venugopal
I edited the question. I only want to read/ evaluate in the js file the vuex state.property value (for evaluation within an if clause within a function), not alter it with actions/ mutations.musicformellons

4 Answers

37
votes

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

7
votes

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)
5
votes
import store from './store'

and than

store.commit('mutation_name', mutation_argument)

if you use js file

1
votes

You can also access actions like:

import store from './store'
store.dispatch('action_name', action_argument)