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));
}