Access vuex state in separate axios template js file - javascript

I have a problem. I have a Vuex state. Also I am making axios request. I have created a separate file for template axios request with predefined header. It looks like this:
import axios from 'axios'
import store from '../store/index'
export default axios.create({
baseURL: 'https://k-3soft.com/',
timeout: 1000,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${store.getters.getToken}`
}
})
The problem is that in this case store in undefined. So how can I import to this /src/axios/request.js file my vuex store?
Also I have tried import { store } from '../store/index'.
My store looks like this:
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex)
export default new Vuex.Store({
namespaced: true,
modules: {
user
},
state: {
url: 'https://icfprod.k-3soft.com/',
token: '',
},
getters: {
getToken: state => state.token
},
})
Also may by anyone can share to view any repository where there is Vuex with modules, axios with file with separate predefined template. Just wanna see how to organize my project's structure. Thanks everyone for help.

Use a factory function to create the axios instance.
// request.js
import axios from 'axios'
const createAxiosInstance = (token) => {
return axios.create({
baseURL: 'https://k-3soft.com/',
timeout: 1000,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
}
}
})
export default createAxiosInstance
Then use it in a module like:
// user.js
import createAxiosInstance from '../request.js'
const userModule = {
// ...
actions: {
async doSomeAction ({ state, commit, rootState }) {
const axios = createAxiosInstance(rootState.token)
const response = await axios.post('/some/api/endpoint')
.then(response => response)
.catch(error => {
// handle error
})
commit('SOME_MUTATION', response.data)
}
}
}

Related

How to import localstorage data on axios create

I have a component inside React for handling URL calls, it simply has a baseurl and headers I use everywhere in my application.
The problem is when there is no data in localStorage I get an error and the whole application stops.
If I use if condition I can't export inside it because export has to be at the top level.
import axios from "axios";
export default axios.create({
baseURL: `http://www.homrz.com/re_homrz/api/admin/`,
// headers: {
// Authorization: `Bearer ${JSON.parse(localStorage.getItem("user")).token}`,
// "Content-Type": "application/json",
// },
});
I think this may help
import axios from "axios";
let token = JSON.parse(localStorage.getItem("user")).token
export default axios.create({
baseURL: `http://www.homrz.com/re_homrz/api/admin/`,
headers: {
Authorization: token ? `Bearer ${token}` ? null,
"Content-Type": "application/json",
},
});
Make one file auth-header.js with below code
export function authHeader() {
let user = JSON.parse(localStorage.getItem('user'));
if (user !== null && user !== "" && user !== undefined) {
return {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + user.token
};
} else {
return {
'Accept': 'application/json',
'Content-Type': 'application/json',
};
}
}
Then use it like below,
import axios from "axios";
import { authHeader } from './auth-header';
export default axios.create({
baseURL: 'http://www.homrz.com/re_homrz/api/admin/',
headers: authHeader(),
});

How to export Axios.create in Typescript

I have this working:
export default axios.create({
baseURL: 'sample',
headers: {
'Content-Type': 'application/json',
},
transformRequest: [
(data) => {
return JSON.stringify(data);
},
],
});
but the problem is once I edited to be like this:
const API = () => {
const token = 'sample'
const api: AxiosInstance = axios.create({
baseURL: 'http://localhost:5000',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
transformRequest: [
(data) => {
return JSON.stringify(data);
},
],
transformResponse: [
(data) => {
return JSON.parse(data);
},
],
});
return api;
};
export default API;
I want it to be an arrow function so I can access the token inside the function.
The problem is once I start to import the arrow function it will create an error not reading POST method
import API from 'apis';
API.post
Is there a way to implement it like an arrow function but will not lose the type definitions or create an error?
You don't loose any type definitions, but you're not using your import as a function.
If you write API().post it will work.
I would suggest doing the following:
import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:5000',
headers: {
'Content-Type': 'application/json',
},
transformRequest: [
(data) => {
return JSON.stringify(data);
},
],
transformResponse: [
(data) => {
return JSON.parse(data);
},
],
});
import store from '../store'
const listener = () => {
const token = store.getState().token
api.defaults.headers.common['Authorization'] = token;
}
store.subscribe(listener)
export default api;
You can access the token here as well.
Just because this is the question you find when you look for my problem, if you use require to import axios, to use the correct type definition you'll have to import ti like that:
const axios = require('axios').default
axios.create(...) // No error
This would give an error:
const axios = require('axios')
axios.create(...) // Error

Axios - update headers on exported axios.create instance

I have one api.js which exports by default an axios.create() instance:
import axios from 'axios'
import Cookies from 'js-cookie'
const api = axios.create({
baseURL: process.env.VUE_APP_API_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${Cookies.get('Token')}`,
Organization: Cookies.get('Organization'),
Company: Cookies.get('Company')
}
})
export default api
Then I import this in multiple files like this:
//api/users.js
import api from './api.js'
const methods = {
postUser (params) {
return api.post('/users', params)
},
getUser (id) {
return api.get('/users/' + id)
}
}
export default methods
However there will be some functions that should update the Cookies Organization and Company and I was wondering if is possible to update the default api instance and automatically update it in all imports that use it. I know a simple page refresh would work but I'm building a SPA and I would like to prevent screen to be manually refreshed.
You can add the headers dynamically, that way the cookies will be read on every request.
import axios from 'axios'
import Cookies from 'js-cookie'
const api = axios.create({
baseURL: process.env.VUE_APP_API_URL,
timeout: 10000,
// Static headers
headers: {
'Content-Type': 'application/json',
},
transformRequest: [function (data, headers) {
// You may modify the headers object here
headers['Authorization'] = `Bearer ${Cookies.get('Token')}`
headers['Organization'] = Cookies.get('Organization')
headers['Company'] = Cookies.get('Company')
// Do not change data
return data;
}],
})
export default api
I would suggest to read about interceptor for axios. (https://github.com/axios/axios#interceptors)
A very basic example would be the following.
Lets assume your webservice would return a response http status 401 header.
You'd intercept the response with the following:
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// happy case its 2XX
return response;
}, async (error) => {
if (error.response.status === 401) {
// do some logic to retrieve a new JWT or Cookie.get()
const jwt = Cookies.get('Token');
const config = error.config;
config.headers['Authorization'] = `Bearer ${jwt}`;
}
return await axios.request(config);
});
The next request will then have an authorization header attached to the request header.

How to wrap into async the Cookies.get of my axios object

I have this axios object, and I have noticed that sometimes it fails to get accesstoken because of async issues.
How would you go about awaiting Cookies.get('accesstoken')
This is my code
import axios from 'axios';
import constants from '../constants.js';
import Cookies from 'js-cookie';
const API = axios.create({
baseURL: `${constants.urlBackend}`,
timeout: 10000,
// headers: {
// 'Content-Type': 'application/json'
// },
});
API.interceptors.request.use(
config => {
var accesstoken = Cookies.get('accesstoken');
if (accesstoken) {
config.headers.Authorization = `Bearer ${accesstoken}`;
} else {
delete API.defaults.headers.common.Authorization;
}
return config;
},
error => Promise.reject(error)
);
export default API;
I dont think I can wrap the API.interceptos.request.use in an async function, or at least it didnt seem to work

How to adapt this axios object with bearer tokens that allows GET, to use POST methods?

I have managed to make this run: How to modify axios instance after exported it in ReactJS?
And it looks like this:
import axios from 'axios';
import constants from '../constants.js';
import Cookies from 'js-cookie';
const API = axios.create({
baseURL: `${constants.urlBackend}`,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
API.interceptors.request.use(
config => {
var accesstoken = Cookies.get('accesstoken');
if (accesstoken) {
config.headers.Authorization = `Bearer ${accesstoken}`;
} else {
delete API.defaults.headers.common.Authorization;
}
return config;
},
error => Promise.reject(error)
);
export default API;
And this is an example usage
getUserList() {
API.get('/userlist')
.then(response => {
this.setState({
userList: response.data
}, () => {
console.log(this.state.userList)
});
})
}
But now im confused because I dont understand how to use this with a post so I can pass some data to it, similar to this
axios({
method: 'post',
url: constants.urlBackend + "/register",
data: qs.stringify({ email, password }),
headers: {
'content-type': 'application/x-www-form-urlencoded;charset=utf-8'
}
})
But using the above object.
API.post('/user/update/'+this.state.rowId).then(response => {
//some sort of body {email,password}
})
Have you tried
API.post(
'/user/update/' + this.state.rowId, {
email,
password
}).then(response => {})

Categories