简体   繁体   中英

getters not update value in Vuex

I don't understand how getters work in Vuex. The problem is when logging out the token in state and localStorage is becoming empty, but not in getters. In created I call this:

created: async function () {
    if (this.$store.getters.shortToken) {
      this.isConfirm = true
    }
    console.log(
      'signining', localStorage.getItem('token'), // ''
      'state', this.$store.state.user.token, // ''
      'getter', this.$store.getters.token // 'old-token'
    )
    if (this.$store.getters.token) {
      await this.$router.push({ path: '/' })
    }
  }

And getters have:

token: state => {
    return localStorage.getItem('token') || state.user.token
  }

And mutation :

SET_TOKEN: (state, payload) => {
      localStorage.setItem('token', payload.token)
      Object.assign(state, payload)
    }

BUT, console log in created gives me empty localStorage token (which is normal) and empty state.token (which is also normal).. But, getters.token gives me token (which is NOT normal), because I gave SET_TOKEN empty token. Why is this happening?
PS. If I'm adding console.log(state.user.token, localStorage.getItem('token')) above return in getters token, so getters.token in created hook is empty... WHY?
Also some using codes in this situation, this is logout method:

methods: {
    async logout () {
      if (await this.$store.dispatch('logOut')) {
        console.log('logged out')
        await this.$router.push({ path: '/signin' })
      }
    }
  }

action logout

async logOut (context) {
    console.log('logggog')
    context.commit('SET_TOKEN', {
      token: ''
    })
    context.commit('SET_USER', {
      user: null
    })
    return true
  }

Getters are meant to compute derived state based on store state .

You are facing this problem because you are returning the value of localStorage.getItem() from your Getter , which is not a value of the store state , thus it is not reactive nor observable .

In your example, Vuex will not recompute the value of the Getter when you call localStorage.setItem() .
It will recompute the Getter's value only when state.user.token is changed.

So, if you want to have the Getter working correctly, return just the value of state.user.token .
You can also add a created hook in your App.vue that would check if there is a token in the localStorage and call the SET_TOKEN mutation, if that is what you were trying to accomplish by calling localStorage.getItem in your Getter:

App.vue

<script>
    created() {
        const token = localStorage.getItem('token');
        if (token != null) {
            this.$store.mutations.SET_TOKEN({ token });
        }
    }
</script>

Nonetheless, be aware of change detection caveats when using Object.assign , because Vuex mutations follow Vue's reactivity rules .

In your mutation you should probably do:

SET_TOKEN: (state, payload) => {
    localStorage.setItem('token', payload.token);
    state.token = payload.token;
}

or if payload is actually state.user you can do:

SET_TOKEN: (state, payload) => {
    localStorage.setItem('token', payload.token);
    state.user = {
       ...payload
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM