Trouble with component not refreshing upon store modification in Vuex

Summary:

If you prefer, I have a video detailing my issue: https://youtu.be/Qf9Q4zIaox8

Concern with Navbar Component Not Updating on Store Change.

The issue I'm facing involves the Navbar component not updating when there is a change in the store. I have divided the component into two sections using v-if and v-else. The v-if section is displayed when the user is logged in, and the v-else section is shown when the user is not logged in.

Upon logging in, the server authenticates the user, and the client triggers a mutation to the store, setting the user and client token. This action also sets a state property called "userIsLoggedIn" to true. However, the Navbar component fails to update immediately after the user logs in, despite the isLoggedIn property being true. The update only occurs upon page refresh.

Navbar Component:

<template>
    <div class="navbar">
        <div class="container">
            <div class="navbar-brand">
                <h1 class="navbar-item">
                    <router-link to="/" class="has-text-black">Logo</router-link>
                </h1>
            </div>

            <div class="navbar-menu">
                <div class="navbar-end" v-if="isLoggedIn">
                    <div class="navbar-item">
                        <router-link to="/play" class="has-text-black">Play</router-link>
                    </div>
                    <div class="navbar-item">
                        {{user.balance.toFixed(2)}}
                    </div>
                    <div class="navbar-item has-dropdown is-hoverable">
                        <a class="navbar-link">
                            {{user.username}}
                        </a>

                        <div class="navbar-dropdown">
                            <div class="navbar-item">Profile</div>
                            <div class="navbar-item">Deposit</div>
                            <div class="navbar-item" @click="logout">Logout</div>
                        </div>
                    </div>
                    <div class="navbar-item">
                        FAQ
                    </div>
                </div>

                <div class="navbar-end" v-else>
                    <div class="navbar-item">
                        <router-link to="/login" class="has-text-black">Login</router-link>
                    </div>
                    <div class="navbar-item">
                        <router-link to="/register" class="has-text-black">Register</router-link>
                    </div>
                    <div class="navbar-item">FAQ</div>
                </div>
            </div>
        </div> <!— container —>
    </div> <!— navbar —>
</template>

<script>

import {mapGetters} from "vuex";
export default {
    name: "Navbar",
    data() {
        return {
            user: this.$store.state.user,
        }
    },
    computed: {
        ...mapGetters([
            "isLoggedIn",
        ])
    },

    methods: {
        logout() {
            this.$store.dispatch("setToken", null);
            this.$store.dispatch("setUser", null);
            this.$router.push({
                path: "/"
            })
        }
    }
}
</script>

Vuex Store:

import Vue from "vue"; 
import Vuex from "vuex";
import createPersistedState from "vuex-persistedstate"

Vue.use(Vuex);

export default new Vuex.Store({
    strict: true, 
    plugins: [
        createPersistedState()
    ],
    state: {
        token: null, 
        user: null, 
        isUserLoggedIn: false, 
    },
    getters: {
        isLoggedIn(state) {
            return state.isUserLoggedIn;
        }
    },
    
    mutations: {
        setToken(state, token) {
            state.token = token;
            if (token) {
                state.isUserLoggedIn = true;
            } else {
                state.isUserLoggedIn = false;
            }
        },
        setUser(state, user) {
            state.user = user; 
        }
    },
    actions: {
        setToken ({commit}, token) {
            commit("setToken", token);
        },
        setUser ({commit}, user) {
            commit("setUser", user);
        }
    }
})

Login Component:

<template>
  <div class="hero is-large">
      <div class="container">
          <div class="hero-body">
            
              <div class="field">
                  <div class="notification is-warning" v-show="error">{{error}}</div>
              </div>

              <h1 class="title">Login</h1>


              <div class="field">
                  <label for="username" class="name">Username</label>
                  <input type="text" class="input" name="username" v-model="username">
              </div>

              <div class="field">
                  <label for="username" class="name">Password</label>
                  <input type="password" class="input" name="password" v-model="password">
              </div>

              <div class="field">
                  <button class="button is-link"
                          @click="login"
                          v-bind:class="{'is-loading': pending}">Login</button>
              </div>
          </div>
      </div>
  </div>
</template>

<script>

import AuthenticationService from "../Services/AuthenticationService";

export default {
  name: "Login", 

  data () {
      return {
          username: "",
          password: "", 
          error: null, 
          pending: false, 
      }
  }, 
  methods: {
      async login () {
          try {
            // SET LOADING SPINNER
            this.pending = true; 

            // API REQUEST
            const response = await AuthenticationService.login({
                username: this.username,
                password: this.password, 
            });

            console.log(response);

            // CLEAR FORM
            this.pending = false; 
            this.username = "";
            this.password = ""; 

            this.$store.dispatch("setToken", response.data.token);
            this.$store.dispatch("setUser", response.data.user);

            this.$router.push({
                name: "Landing"
            })
          } catch (error) {
              console.log(error);
          }
      }
  }
}
</script>

Answer №1

Upon review, it appears that the issue lies in not setting the isUserLoggedIn variable to true when the user logs in. To resolve this, you need to create an action and mutation to update the isUserLoggedIn status upon successful login.

Action

setUserLoggedIn ({commit}) {
 commit("setUserLoggedIn", true);
}

Mutation

setUserLoggedIn(state, payload) {
 state.isUserLoggedIn = true
}

In the Login component, modify the following lines:

this.$store.dispatch("setToken", response.data.token);
this.$store.dispatch("setUser", response.data.user);

to:

this.$store.dispatch("setToken", response.data.token);
this.$store.dispatch("setUser", response.data.user);
this.$store.dispatch("setUserLoggedIn");

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

Executing a function by clicking on an element with the `ng-click` directive within a Bootstrap modal

I'm working on an app that allows users to submit posts for review. When a user clicks the add post button, I have a Bootstrap modal pop up to confirm their choice. Within this modal, there is a "confirm" button that should trigger a function. Strang ...

Can you explain the contrast between the functions 'remove' and 'removeChild' in JavaScript?

I have recently coded an HTML page in order to gain a better understanding of how element removal functions. Code: <html> <head> <script> var childDiv = null; var parent1 = null; var parent2 = null; function ...

Tips for utilizing append and remove to modify HTML forms

Currently, I am working on a WordPress project that requires the use of append and remove for dynamically changing forms in HTML. I attempted to implement this functionality, but encountered some errors. The code snippet below provides a brief overview of ...

What is the best way to send a JSON response from a Symfony2 controller?

I am utilizing jQuery to modify my form, which is created using Symfony. The form is displayed within a jQuery dialog and then submitted. Data is successfully stored in the database. However, I am unsure if I need to send some JSON back to jQuery. I am ...

Vue - The urge to push a nested object

I am currently working on a form that involves nested objects in Vue and The Quasar Framework. My goal is to include questions and have the ability to add as many answers as needed for each question. However, I am facing difficulties when trying to click t ...

Removing White Spaces in a String Using JavaScript Manually

I have created my own algorithm to achieve the same outcome as this function: var string= string.split(' ').join(''); For example, if I input the String: Hello how are you, it should become Hellohowareyou My approach avoids using ...

Utilize SCSS values within TypeScript by applying them on a class level

let changeClassDisplay = document.getElementsByClassName('sidebar'); for (var i = 0; i < changeClassDisplay.length; i += 1) { changeClassDisplay[i].style.display = 'block'; } I encountered an issue with this code whe ...

Transform the object into an array of JSON with specified keys

Here is a sample object: { labels: ["city A", "city B"], data: ["Abc", "Bcd"] }; I am looking to transform the above object into an array of JSON like this: [ { labels: "city A", data: "Abc" }, { labels: "city B", data: "Bcd" }, ]; ...

Jquery Banner Fade In animation malfunctioning

I am facing an issue with my banner on various browsers, especially IE 7,8, and possibly 9. When the fade-in effect is applied at the bottom of the banner, the shadows underneath turn black. Is there anyone who can help me resolve this issue? Website: ww ...

Setting up camera in ThreeJS

I am brand new to ThreeJS and currently trying to incorporate it into my web application. I have encountered a problem with configuring the camera. Currently, I have a perspective camera that is able to look at and move in every direction within my scene. ...

"What is the best approach to adjusting the width of one div based on the width of another div using CSS Grid

As a beginner in programming, I'm trying to work with CSS Grid but facing some challenges. My goal is to create a component with two columns: the left column should have a width of minmax(570px, 720px), and the right column should be minmax(380px, 10 ...

Trouble with $http response not appearing in AngularJS application

Currently, I am in the process of developing an angularjs application and encountering a challenging issue with setting up the $http connection to a php file. The header is displaying a response that I echoed from php. Nevertheless, two key problems persis ...

Is there a way to implement JavaScript within my Blazor server razor page to modify the styling of a blazor bootstrap button after a form submission?

I am currently working on a Blazor server application where I am looking to add a special functionality. My goal is to have the accordion header change to red if validation fails, meaning if there is no input in the field. view image here //index.razor pa ...

How to Modify a File Inside a Compressed File Using JSZip

Is it possible to modify a file within a zipped file using JSZip? I have searched for answers and reviewed the API, but I am unable to find a solution. Any assistance on this matter would be highly appreciated. Thank you in advance! ...

The output of jQuery('body').text() varies depending on the browser being used

Here is the setup of my HTML code: <html> <head> <title>Test</title> <script type="text/javascript" src="jQuery.js"></script> <script type="text/javascript"> function initialize() { var ...

The cURL command successfully executes the request, however, it fails to work in both Postman and web browsers

A problem arises when the Node Js (express) server responds to requests using cUrl, resulting in an infinite load. However, when requested via Postman or a browser, there are no errors but still faces issues. Despite searching for solutions, none of the s ...

What's the best way to constrain a draggable element within the boundaries of its parent using right and bottom values?

I am currently working on creating a draggable map. I have successfully limited the draggable child for the left and top sides, but I am struggling to do the same for the right and bottom sides. How can I restrict the movement of a draggable child based o ...

Executing the event handler only once

In my React project, I have a button that toggles a boolean state. However, I realized that the button can both set and unset the state due to its toggle functionality. I only want the state to be changed once. Is there a different function I can use ins ...

The element will only show up upon resizing (in Safari web browser)

I am facing a problem with a button styled using the class btn-getInfo-Ok <button class="btn-getInfo-Ok">Hello</button> in my style.css file .btn-getInfo-Ok { color:white !important; margin: 0 auto !important; height:50px; bottom:0; ...

Localhost is unable to process AngularJS routes containing a dot in the URL

When using the route provider and setting this specific route: .when('/:name/:id', { It successfully navigates to my desired path and executes the code when I enter: https://localhost.myapp.com:9000/Paul/123 However, it fails to work with this ...