Home > Enterprise >  How to show button checking a localStorage key with Vue?
How to show button checking a localStorage key with Vue?

Time:09-27

When I log out I delete the token. Here is how I check if the token is deleted:

  const isLoggedOut = () => {
    let token = window.localStorage.getItem('token')
    if (token === undefined || token === null || token.length === 0) {
      console.log("user is logged out")
      return true
    }
    else {
      console.log("user is logged in")
      return false
    }
  }

Inside the navbar I want the Login button to be hidden if the user is logged in. This is how the navbar looks like:

  <nav >
    <router-link  :to="{ name: 'Home' }">Home</router-link>
    <ul >
        <li >
            <router-link  :to="{ name: 'Login' }" v-if="isLoggedOut">Login</router-link>
        </li>
        <li >
            <router-link  :to="{ name: 'Register' }">Register</router-link>
        </li>
        <li >
            <router-link  :to="{ name: 'Dashboard' }">Dashboard</router-link>
        </li>
        <li >
            <button  @click="logOut">Logout</button>
        </li>
    </ul>
  </nav>

Later edit, this is the App.vue file without the styles. I log in and Login button still appears in the navbar.

<script setup>
  import { reactive,ref, computed } from 'vue'
  import { useRouter } from "vue-router"

  const router = useRouter()

  const token = ref(null);
  const setToken = (token) => {
    token.value = token;
    window.localStorage.setItem('token', token)
  } 
  const clearToken = () => {
    token.value = null;
    window.localStorage.removeItem('token')
  }

  const isLoggedOut = computed(() => token.value === null)

  const logOut = () => {
    clearToken()
    router.push({name:'Login'})
  }

</script>

<template>
  <nav >
    <router-link  :to="{ name: 'Home' }">Home</router-link>
    <ul >

        <!-- Show Login button only if user is logged out -->
        <li >
            <router-link  :to="{ name: 'Login' }" v-if="isLoggedOut">Login</router-link>
        </li>
        
        <li >
            <router-link  :to="{ name: 'Register' }">Register</router-link>
        </li>
        <li >
            <router-link  :to="{ name: 'Dashboard' }">Dashboard</router-link>
        </li>
        <li >
          <button  @click="logOut">Logout</button>
        </li>
    </ul>
  </nav>
  <router-view/>
</template>

CodePudding user response:

window.localStorage.getItem('token') is not reactive. If the value changes, you will not be notified.

Instead of getting logged in state from localStorage, you can manage it through internal state which will then manage the local storage.

for example:

const token = ref(null);
const setToken = (value) => {
  token.value = value;
  window.localStorage.setItem('token', token)
} 
const clearToken = () => {
  token.value = null;
  window.localStorage.removeItem('token')
}
const isLoggedIn = computed(()=>token.value !== null)

then you can use isLoggedIn as a reactive (computed) value.

You can store this in a separate auth.js and export the methods and token.

example

CodePudding user response:

The button is still visible because the component (App.vue in your case) is not reloaded, meaning the check whether you have a token or not is not performed, respectively the computed is not going to be updated because as mentioned above window.localStorage is not reactive.

One way to overcome this is to use a store (pinia/vuex/composable that will hold the value all the time) and router hooks, like beforeRouteEnter or the global one - beforeEach.

You can also try to make localStoragereactive like in this example here

Which might be overkill.

Just make sure you moved token functions and operations in a separated file (or even as a composable)

  • Related