Search code examples
axioscomponentsvuejs3store

Call api with axios since my component and my store


I'm new to Vue 3 (cli) and I'm not at all comfortable with front-end technology, so I'm having a hard time understanding the information I'm reading.

I succeeded in creating a registration/login interface with an api and JWT. The user information needs to be persisted everywhere in the project I'm doing to train myself, so I configured axios in my store.

store/index.js

import { createStore } from 'vuex'
import axios from 'axios';

const api = axios.create({
  baseURL: 'http://127.0.0.1:7000'
});

let user = localStorage.getItem('user');
if(null === user) {
  user = {uuid: '', token: ''};
} else {
  try {
    user = JSON.parse(user);
    api.defaults.headers.common['Authorization'] = 'Bearer ' + user.token;
  } catch (e) {
    user = {uuid: '', token: ''};
  }
}
export default createStore({
  state: {
    status: '',
    user: user,
    userInfos: {},
  },
  mutations: {
    [...]
  },
  getters: {
  },
  actions: {
    [...]
  },
  modules: {
  }
})

I would like to be able to use api from my components. I have had several approaches:

1 - I have imported axios into my component, but this is not correct at all, as I will need axios in all my components.

2 - I've looked at different documentations that explain how to configure axios globally, but no two are the same and I couldn't get anything to work.

3 - I've tried calling api through strangenesses like this.$store.api in my methods, but obviously this is abused.

Can anyone help me understand what is the right way to use axios from my components and from the store with only one configuration? Knowing that I need to be able to keep my headers up to date for authentication with the Bearer Token (a mutation updates it in the store at user login).

main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap/dist/js/bootstrap.js'

import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faMedal } from '@fortawesome/free-solid-svg-icons'
import { faLaptopMedical } from '@fortawesome/free-solid-svg-icons'
import { faCookieBite } from '@fortawesome/free-solid-svg-icons'
import { faCoins } from '@fortawesome/free-solid-svg-icons'
import { faHourglassStart } from '@fortawesome/free-solid-svg-icons'
import { faUpRightFromSquare } from '@fortawesome/free-solid-svg-icons'
import { faInfo } from '@fortawesome/free-solid-svg-icons'
import { faGears } from '@fortawesome/free-solid-svg-icons'

library.add(
    faMedal,
    faCoins,
    faLaptopMedical,
    faCookieBite,
    faHourglassStart,
    faUpRightFromSquare,
    faInfo,
    faGears
);

createApp(App)
    .component('font-awesome-icon', FontAwesomeIcon)
    .use(store)
    .use(router)
    .mount('#app')

Thank you very much for your help.


Solution

  • I don't know if this is the right way, but by doing so, it allows me to use the store api in my components.

    store/index.js
    
    state: {
        api: {},
        [...]
    },
    mutations: {
        setApi: function (state, api) {
          state.api = api;
        },
        connexionUser: function (state, user) {
          state.user = user;
          api.defaults.headers.common['Authorization'] = 'Bearer ' + user.token;
          state.api = api;
        },
        [...]
    },
    actions: {
         setApi: ({commit}) => {
          commit('setApi', api);
        },
        [...]
    },
    
    App.vue
    
    mounted() {
        this.$store.dispatch('setApi');
        [...]
      }
    

    Like this, offline, it loads api which is set at the top of my store (see in my question) and when I log in, I update api in state to have JWT authentication.