Search code examples
vue.jsvuejs2vuexvue-resource

Vue resource inside Vuex action - "this is null" error


I am trying to make a GET call from inside a store action. However my Vue.http.get() call throws a TypeError "this is null".

I am at a total loss, and I haven't found anyone else with this specific issue elsewhere. Any help would be appreciated. Thanks

Walkthrough

  1. User navs to /login/
  2. Submits login
  3. Authenticated and token received
  4. Dispatches action to save token and retrieve profile
  5. Error occurs when trying to use Vue.http inside action

Note, the token correctly gets stored in state and localStorage.

Login.vue

methods: {
    submit() {
        this.$http.post(
            this.loginEndpoint,
            this.object
        ).then(response => {
            this.$store.dispatch({
                "type": "auth/save",
                "token": response.body.key,
            }).then(() => {
                this.$router.push({name: "home"})
            }).catch(error => {
                console.log(error)
            })
        }).catch(error => {
            console.log(error)
        })
    }
}

Store

import Vue from 'vue'
import Vuex from 'vuex'
import Auth from '../stores/auth.js'


// plugins
Vue.use(Vuex)


export default new Vuex.Store({
    modules: {
        auth: Auth,
    },
})

auth.js - store module

import Vue from 'vue'


export default {
    namespaced: true,

    state: {
        token: null,
        profile: {},
    },

    mutations: {
        setProfile(state, payload) {
            state.profile = payload.profile
        },

        setToken(state, payload) {
            state.token = payload.token
        },
    },

    actions: {
        save: (context, payload) => {
            return new Promise((resolve, reject) => {
                const url = "/rest-auth/user/"

                context.commit('setToken', {
                    token: payload.token,
                })

                localStorage.setItem("token", payload.token)

                console.log("get user profile")

                // *** Error below calling Vue.http.get ***
                // TypeError: this is null
                Vue.http.get(url).then(response => {
                    console.log("Profile received")

                    context.commit('setProfile', {
                        profile: response.body,
                    })

                    localStorage.setItem("profile", response.body)
                    resolve()

                }).catch(error => {
                    reject(error)
                })
            })
        },
    },
}

Stack Trace

TypeError: this is null
Stack trace:
@webpack-internal:///10:42:9
exec@webpack-internal:///6:1150:21
Client/<@webpack-internal:///6:1179:13
PromiseObj@webpack-internal:///6:200:24
Client@webpack-internal:///6:1143:16
Http@webpack-internal:///6:1400:12
Http[method$$1]@webpack-internal:///6:1431:16
save/<@webpack-internal:///14:112:17
save@webpack-internal:///14:90:20
wrappedActionHandler@webpack-internal:///7:604:15
dispatch@webpack-internal:///7:347:7
boundDispatch@webpack-internal:///7:272:12
submit/<@webpack-internal:///17:100:17

Solution

  • It turns out that code in my Vue instance was causing the problem. There I was pushing a csrf value to the X-CSRFTOKEN header.

    I am using Django and DRF. I just switched from SessionAuthentication to using TokenAuthentication and now have learned that passing the csrf token is not needed.

    The code below is from my main.js and after removing it the issue is resolved.

    The offending code

    /* Add the csrf token to the request header */
    Vue.http.interceptors.push(function(request, next) {
        let token = this.$cookie.get("csrftoken")
        request.headers.set('X-CSRFTOKEN', token)
        next()
    });
    

    Exactly why this caused the TypeError to be thrown I can't say.