Currently, whenever a user logs in using correct credentials, a token get saved in the local storage. Now I’m trying to hide signin and signup after the user logs in.
The code I currently have works relatively alright, however, I noticed that when the user logs in, the signin and signup routes do not disappear until the page is refreshed which is not very SPA like.
Why is this happening?
<template> <div class="nav-header"> <div class="wrapper"> <ul class='nav-ul'> <router-link to="/" tag='li' active-class='active' exact><li><a>Home</a></li></router-link> <router-link to="/signup" v-if="!isLoggedIn" tag='li' active-class='active' exact><li><a>Sign Up</a></li></router-link> <router-link to="/signin" v-if="!isLoggedIn" tag='li' active-class='active' exact><li><a>Sign In</a></li></router-link> </ul> </div> </div> </template> <script> export default { computed: { isLoggedIn() { return !!window.localStorage.getItem('token') } } } </script>
App.vue
<template> <div id="app"> <app-header></app-header> <router-view></router-view> </div> </template> <script> import Header from './components/header.vue'; export default { components: { appHeader: Header } } </script>
Sigin.vue
<template> <div> <input v-model="email" placeholder="Your Email..."> <input v-model="password" placeholder="Your Password..."> <button v-on:click.prevent="signin" type="submit" name="submit">Submit</button> </div> </template> <script> import axios from 'axios' axios.defaults.baseURL = 'http://94.155.24.68/api'; export default { data: function() { return { email: '', password: '' } }, methods: { signin: function(){ axios.post('/signin', { email: this.email, password: this.password }) .then((response) => { console.log(response); const token = response.data.token; localStorage.setItem('token', token); }).catch((error) => console.log(error)); } } } </script>
Advertisement
Answer
The reason this doesn’t work is because you are trying to watch for changes on the non reactive localStorage.
To make it reactive I tend to create a global Vue instance using Vue.prototype (allowing you to use it in all your components)
Vue.prototype.$localStorage = new Vue({ data: { // token property returning the ls token value token: window.localStorage.getItem('token') }, watch:{ // watcher listening for changes on the token property // to ensure the new value is written back to ls token(value){ window.localStorage.setItem('token', value) } } }) // you can now access the token in all your components using // this.$localStorage.token get the token value // this.$localStorage.token = 'tkn'; set the token value
Demo https://codepen.io/jakob-e/pen/LMJEYV?editors=1010
To implement it in your solution you can do:
// in the header component computed: { isLoggedIn(){ return this.$localStorage.token !== ''; } } // in the signin component signin(){ axios.post('/signin', { email: this.email, password: this.password }) .then((response) => { console.log(response); const token = response.data.token; this.$localStorage.token = token; }) .catch((error) => console.log(error)); }