Calling Vuex mutator within Axios interceptor

Viewed 187

I would like to trigger a mutation from within an interceptor. In this case, trigger the logout mutation whenever Axios encounters an http 403.

I imported Vuex mutations and mapped as I've done elsewhere but I have not been able to access it within the Axios interceptor error function. I've added my interceptor config in App.vue's created() method.

I've tried the syntax from these 2 questions without success, most likely due to my project using modules, and the Axios config being located in a created() method.

  1. https://www.reddit.com/r/vuejs/comments/eq5eej/question_how_to_access_vuex_store_modules_mode_in/ <- Axios config in a seperate file, is this the best practice?
  2. Can't access Vuex storage mutation inside Axios interceptor <- Not using modules

App.vue

<script>
import { mapMutations } from "vuex";
import axios from 'axios';
export default {
  methods: {
    ...mapMutations(["logout"])
  },
  created(){
    axios.interceptors.response.use(
      function (response) {
        return response;
      }, 
      function (error) {
        if (error.response.status === 403) {
          this.logout()
            .then(() => {
              this.$router.push("/");
            })
        }
    });
  }
}
</script>

EDIT Adding screenshot of results from the below answers enter image description here

2 Answers

You are close. The only thing that is stopping you is that you were declaring functions using the function() {} declaration, rather than the "fat-arrow" function declaration, which was creating a new scope (this was different). You should see the differences between the two changes below.

// Your current script.
import { mapMutations } from "vuex";
import axios from 'axios';
export default {
  methods: {
    ...mapMutations(["logout"])
  },
  created(){
    axios.interceptors.response.use(
      function (response) {
        return response;
      }, 
      function (error) {
        if (error.response.status === 403) {
          this.logout()
            .then(() => {
              this.$router.push("/");
            })
        }
    });
  }
}


// Updated
import { mapMutations } from "vuex";
import axios from 'axios';
export default {
  methods: {
    ...mapMutations(["logout"])
  },
  mounted() {
    axios.interceptors.response.use(
      (response) => response, 
      (error) => {
        if (error.response.status === 403) {
          return this.logout()
            .then(() => this.$router.push("/"));
        }
        else {
          return Promise.reject(err);
        }
    });
  }
}
</script>

You will either need to use an arrow function or bind the this context to your function in order to access this correctly

<script>
import { mapMutations } from "vuex";
import axios from 'axios';
export default {
  methods: {
    ...mapMutations(["logout"])
  },
  created(){
    axios.interceptors.response.use(
      function (response) {
        return response;
      }, 
      (error) => {
        if (error.response.status === 403) {
          this.logout()
            .then(() => {
              this.$router.push("/");
            })
        }
      }
    );
  }
}
</script>

or

<script>
import { mapMutations } from "vuex";
import axios from 'axios';
export default {
  methods: {
    ...mapMutations(["logout"])
  },
  created(){
    axios.interceptors.response.use(
      function (response) {
        return response;
      }, 
      function (error) {
        if (error.response.status === 403) {
          this.logout()
            .then(() => {
              this.$router.push("/");
            })
        }
      }.bind(this)
    );
  }
}
</script>
Related