Values in Vuex do not get updated by getters

I'm having trouble understanding the functionality of getters in Vuex. The issue arises when I log out the token and find that the state and localStorage are empty, but the getters still contain the old token value. In the created lifecycle hook, I have the following code:

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: '/' })
    }
  }

The getters section contains:

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

And for the mutation:

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

However, the console log within created shows an empty localStorage token (expected behavior), empty state.token (also expected).. But, getters.token displays the token value (unexpected), despite setting SET_TOKEN with an empty token. Why is this happening?
PS. If I add a

console.log(state.user.token, localStorage.getItem('token'))
above the return statement in the getters token, the getters.token in the created hook becomes empty... WHY?
Here are some relevant codes for handling this scenario, starting with the logout method:

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

Action for logging out

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

Answer №1

Getters play a crucial role in computing derived state based on the store state.

The issue arises when you return the value of localStorage.getItem() from your Getter, as it is not part of the store state and therefore not reactive or observable.

In Vuex, the Getter will only recalculate its value when there are changes to state.user.token, not when localStorage.setItem() is called.

To ensure that the Getter functions correctly, simply return the value of state.user.token. Additionally, consider adding a created hook in your App.vue to check for a token in localStorage and trigger the SET_TOKEN mutation if needed:

App.vue

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

Remember to be cautious of change detection caveats when using Object.assign because Vuex mutations adhere to Vue's reactivity rules.

In your mutation function, consider either:

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

or if payload represents state.user:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is relying on jQuery to submit a form without the use of PHP secure?

My website has a user account creation form with a "submit" button that is actually an html type='button', not a true submit button. When this button is clicked, I rely on jQuery to call ('#form').submit(); in order to submit the form. ...

Is the current version of NPM React-router too cutting-edge for your needs

When I use the command npm -v react-router on my React app, it shows version 6.9.0. However, when I check the npmjs page for react-router, the latest version available is 5.0.1. How can this discrepancy be explained? ...

Tips for displaying CSS recommendations in JetBrains IDE (such as PyCharm) for your Nuxt project

Can anyone provide guidance on how to display CSS suggestions in JetBrains IDE (such as PyCharm)? They work fine in normal Vue projects with Vuetify, but for some reason they are not appearing in my Nuxt project. I currently have them working in my Vue pr ...

A pair of demands within an express service

Currently, I'm facing an issue in a project where I am attempting to create a service using Express that makes two external API calls. However, I am encountering an error in Express that is difficult to comprehend. It seems like my approach might be i ...

What is the most effective way to dynamically incorporate external input into a SlimerJS script?

Could use some assistance with SlimerJS. My current program requires intermittent input from stdin to proceed with the next task. The code below functions effectively when using PhantomJS+CasperJS for reading external input, but encounters difficulties wi ...

Unity3D: Troubleshooting a Code Issue

Encountering an issue with my code and struggling to find a solution. I've tried moving my c# script up to the standard assets folder as suggested in my research but it didn't resolve the problem. Any assistance would be greatly appreciated! Than ...

Tips for resolving the 'route.search' bug in Express.js

I recently started working on a basic Express app (with Node) and I am in the initial setup phase. However, I have encountered an error that is proving to be quite challenging to resolve. Despite my attempts to search for solutions online and browse throu ...

I'm looking for a way to implement a jQuery-style initialization pattern using TypeScript - how can I

My library utilizes a jQuery-like initialization pattern, along with some specific requirements for the types it should accept and return: function JQueryInitializer ( selector /*: string | INSTANCE_OF_JQUERY*/ ) { if ( selector.__jquery ) return select ...

Encountering an error in resolving symbol values statically within the Angular module

Following a helpful guide, I have created the module below: @NgModule({ // ... }) export class MatchMediaModule { private static forRootHasAlreadyBeenCalled: boolean = false; // This method ensures that the providers of the feature module ar ...

Is it necessary to have both index.js and Component.js files for a single component in React?

Continuously analyzing various projects, I often come across authors who organize their file structures in ways that are perplexing to me without proper explanation. Take, for instance, a component where there is a folder named Header. Inside this folder, ...

Incorporating a React element into a JavaScript object's property: A comprehensive guide

Below is a React Element named Info that has been attached to a Javascript object named myObj: let Info = ( <Info type="green" /> ); let myObj = { ReactComp: Info }; Now, the goal is to render the Info component using the above myObj objec ...

Restrict the maximum and minimum time that can be entered in an HTML input

I've implemented a basic code feature that allows users to input minutes and seconds on my React website. <div> <span> <input defaultValue="0" maxlength="2"/> </span> <span>m</span> <spa ...

Use YUI to parse JSON data enclosed in square brackets and curly braces within a packet

Recently, I have been diving into the world of JSON, JavaScript, and YUI while working on a homework assignment. The JSON packet I am dealing with has the following structure: [{"id":"1234", "name":"some description","description":"url":"www.sd.com"}, {sa ...

Assign a background image to a button using an element that is already present on the page

Is there a way to set the background-image of a button without using an image URL? I am hoping to use an element already in the DOM as the background-image to avoid fetching it again when the button is clicked. For example, caching a loading gif within the ...

The mysterious workings of the parseInt() function

As I begin my journey to self-teach JavaScript using HeadFirst JavaScript, I've encountered a minor obstacle. The chapter I'm currently studying delves into handling data input in forms. The issue arises when I attempt to utilize the updateOrder( ...

Guide to building a react-redux application with a Node server as the backend

Hey there! I'm looking to build a react-redux app with a node server as the backend. Is it feasible for the node server to serve the react-redux app instead of having react-redux run on one port and node on another? Any suggestions on how to kick thi ...

What is the process for setting environment variables in a Svelte project?

I'm brand new to working with Svelte and I want to incorporate environment variables like base_url into different components. I've read that I can set up a store to hold these values, for example: const DataStore = writable([ { base_url: & ...

Using Laravel and AJAX to save multiple selected filters for future use

I've been struggling with this issue for a few weeks now and just can't seem to wrap my head around it. On my webpage, I've implemented four filters: a search filter, a year filter, a launch-site filter, and a country filter. Each of these ...

Using nested v-for loops in Vue.js

Is there a way to access individual object items within a nested object using v-for in Vue.js? This is the data structure: flights: [ { "airline": "BA", "airport": "EBJ", "status": { "_code": "A", "_time": "2018-03-02T14:19:00Z" ...

Experiencing an unusual issue with grunt: The Gruntfile.js seems to be missing the 'flatten' method

Encountering an unusual error message while attempting to run grunt stated: TypeError: Object Gruntfile.js has no method 'flatten' Being a beginner with node.js, npm, and grunt, I believe my installation of node, npm, and grunt was done correctl ...