Reputation: 81
I am trying to perform user login with Vuejs and Django. I use vuex and django restframework as a component. When I use the user login form with Vuex store, django creates token for the user. However, vue js does not detect the generated user token. token is returning as undefined.
My store.js codes
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
status: '',
token: localStorage.getItem('token') || '',
user : {}
},
mutations: {
auth_request(state){
state.status = 'loading'
},
auth_success(state, token, user){
state.status = 'success'
state.token = token
state.user = user
},
auth_error(state){
state.status = 'error'
},
logout(state){
state.status = ''
state.token = ''
},
},
actions: {
login({commit}, user){
return new Promise((resolve, reject) => {
commit('auth_request')
axios({url: 'http://localhost:8001/api/v1/token/create', data: user, method: 'POST' })
.then(resp => {
const token = resp.data.token
const user = resp.data.user
localStorage.setItem('token', token)
// Add the following line:
axios.defaults.headers.common['Authorization'] = 'Bearer ${token}'
commit('auth_success', token, user)
resolve(resp)
})
.catch(err => {
commit('auth_error')
localStorage.removeItem('token')
reject(err)
})
})
},
register({commit}, user){
return new Promise((resolve, reject) => {
commit('auth_request')
axios({url: 'http://localhost:8001/api/v1/users/create', data: user, method: 'POST' })
.then(resp => {
const token = resp.data.token
const user = resp.data.user
localStorage.setItem('token', token)
// Add the following line:
axios.defaults.headers.common['Authorization'] = 'Bearer ${token}'
commit('auth_success', token, user)
resolve(resp)
})
.catch(err => {
commit('auth_error', err)
localStorage.removeItem('token')
reject(err)
})
})
},
logout({commit}){
return new Promise((resolve, reject) => {
commit('logout')
localStorage.removeItem('token')
delete axios.defaults.headers.common['Authorization']
resolve()
})
}
},
getters : {
isLoggedIn: state => !!state.token,
authStatus: state => state.status,
}
})
Main.js
...
import store from './store';
import Axios from 'axios';
Vue.prototype.$http = Axios;
const token = localStorage.getItem('token')
if (token) {
Vue.prototype.$http.defaults.headers.common['Authorization'] = 'Bearer ' + token
}
...
Login page
...
data() {
return {
username: '',
password: ''
}
},
methods: {
login: function() {
let username = this.username
let password = this.password
this.$store.dispatch('login', { username, password })
.then(() => this.$router.push('/'))
.catch(err => console.log(err))
}
}
...
Upvotes: 0
Views: 1359
Reputation: 450
If anyone else runs into it:
I have it calling some private helpers:
function setDefaultAuthHeaders(state) {
axios.defaults.headers.common.Authorization = state.currentToken
? `Bearer ${state.currentToken.token}`
: ''
}
function saveState(key, state) {
window.localStorage.setItem(key, JSON.stringify(state))
}
Then, in my mutation I have something to call it:
export const mutations = {
SET_TOKEN(state, newToken) {
state.currentToken = newToken
saveState('currentToken', newToken)
setDefaultAuthHeaders(state)
},
}
Upvotes: 0
Reputation: 489
Your main.js runs before store.js. The token only be generated after you call login action in store.js. After that nothing trigger the localStorage.getItem()
method again, so the token remains undefined there.
The easiest way to get token is put another entry in getters for token, then use mapGetters to get it from any component you want.
Upvotes: 1