Vuex state is sometimes empty (undefined), especially when I refresh the page and sometimes it works - vue.js

Vuex state is sometimes empty (undefined), especially when I refresh the page. And sometimes it works.
action:
getSkills(context) {
let url = "/skills";
const headers = {
"x-api-key": process.env.VUE_APP_SIRH_X_API_KEY,
Authorization: localStorage.getItem("access_token"),
};
return axios({
method: "get",
url: url,
headers: headers,
}).then((response) => {
context.commit("getSkill", response.data.data.skills);
}).catch((e) => {
console.log(e);
});
},
getter:
Skills: (state) => state.Skills,
mutation :
getSkill(state, skills) {
state.Skills = skills;
},
state :
Skills: [],
and the vue :
computed: {
...mapState({}),
...mapGetters(["Candidate", "Skills"])
},
mounted() {
this.getSkills();
this.id = this.$route.params.id;
this.Skills.forEach(element => this.skill_list.push(element.skill_name));
},
methods: {
...mapActions(["attachSkillCandidate", "getSkills"]),
}
Can anyone help me to solve this issue ?
Thanks!

The getSkills action is performing an asynchronous request. You need to wait for the request to finish before you can access this.Skills otherwise the data will not be set yet.
You need async and await (the "modern" solution):
async mounted() {
await this.getSkils();
this.id = this.$route.params.id;
this.Skills.forEach(element => this.skill_list.push(element.skill_name));
}
or:
mounted() {
this.getSkils().then(() => {
this.id = this.$route.params.id;
this.Skills.forEach(element => this.skill_list.push(element.skill_name));
});
}

Related

How to properly await Nuxt calls with async/await or .then

Im trying to fetch an API using chaining with .then but I don't figure it out I try like:
async fetch() {
let path = this.$nuxt.context.route.path
this.response = await axios.get(
`/api${path}`,
{
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json'
}
}
).then((res) => {
this.results = res.data.content.slice(0,40);
return results();
})
.then((res) => {
this.results2 = res.data.content.slice(20,40);
return results2();
})
},
For my API data load: when results is finish /results2 start to load, for using it with $fetchState.pending
What will be the best way of doing it? I'm trying to adapt the answer from here but no success so far.
This kind of code should be working fine
<script>
export default {
async fetch() {
this.response = await axios
.get(`/api${this.$route.path}`, { // faster than this.$nuxt.context.route.path
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json',
},
})
.then((res) => { // ❌ this is useless because you're already using await above
const results = res.data.content.slice(0, 40)
return results()
})
.then((res) => { // ❌ this is useless because `slice` is NOT async
const results2 = res.data.content.slice(20, 40)
return results2()
})
},
}
</script>
Otherwise, I can also recommend a better approach overall, using async/await and not mixing it with .then at all, like this
<script>
export default {
async fetch() {
const response = await axios.get(
`/api${this.$route.path}`,
{
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json',
},
}
)
const results = response.data.content.slice(0, 40)
const results2 = results.data.content.slice(20, 40)
},
}
</script>
PS: note that some things are not async, hence do not need await (or .then at all).
It can even be shorten to the following
<script>
export default {
async fetch() {
const response = await this.$axios.$get( // 👈🏻 using the shortcut $get
`/api${this.$route.path}`,
{
headers: {
'X-AUTH-TOKEN': process.env.SECURE_TOKEN,
'Content-Type': 'application/json',
},
}
)
const results = response.content.slice(0, 40) // 👈🏻 no need for `.data` here
const results2 = results.content.slice(20, 40) // 👈🏻 same here
},
}
</script>
Thanks to the shortcuts available with the axios module that you should be using anyway.
As of why you should use async/await, it's just more lisible and available everywhere already (IE is dead). Here is some more info about the whole async/await thing: https://javascript.info/async-await
Far prettier than this kind of syntax (also named callback hell)

Cancel an axios request, when not having the fetch in useEffect

I am trying to implement the cancel request function for my axios post. I created own js files for the functions and I am importing them into my screens. Here is an example
App.js
cancelToken.current = axios.CancelToken.source()
async function getFeed() {
let x = await service.getUserFeed(user_id, cancelToken);
setData(x); }
getFeed();
return () => {
cancelToken.cancel();
}
},[user_id]);
service.js:
getUserFeed: async (token, user_id, source) => {
let x;
await axios.post(Default.apiEndpoint + 'feed',
{
},
{
cancelToken: source.token,
headers: {
'Accept': "application/json",
'Content-Type': "application/json",
'user_id': user_id,
}
}).then(response => {
x = response.data;
}).catch(error => {
if (axios.isCancel(error)) {
console.log('Request canceled', error.message);
}
else {
x = error.response.status;
}
});
return x;
},
If I am calling the request in the hook itself it is working. So I am not even sure, if it is possible, because the request is not triggered, when the user leaves the page. So I would need to cancel the request in the service.js itself (I guess). Did anyone implement that already and can help me here?
Thanks

React native axios call throws 403 but postman correctly outputs the data

I'm working on a RN app, which has redux in it. Now I can login with the help of jwt but when Im trying the to get the data from my other component its giving me 403 error. Please find below the relevant code.
Here is my reducer:
const initState = {
isLoadingCollegeDashList : false,
collegeDashList:{},
collegeDashListFail:false
}
const collegeReducer = ( state = initState, action) => {
switch(action.type){
case 'IS_LOADING_COLLEGE_DASH_LIST' :
return{
...state,
isLoadingCollegeDashList: true,
collegeDashList : false
}
case 'COLLEGE_DASH_LIST' :
return {
...state,
isLoadingCollegeDashList : false,
collegeDashList : true,
userData : action.userData
}
case 'COLLEGE_DASH_LIST_FAIL' :
return{
...state,
isLoadingCollegeDashList:false,
collegeDashList: false,
collegeDashListFail: action.error
}
default :
return state
}
}
and here's my action that's making get request
export const populateCollege = (token) => {
const headers = {
'api-secret' : ...secret...,
'authorization':...authToken...,
'Content-Type': 'application/json',
}
return dispatch => {
dispatch(isLoadingCollegeDashList(true));
return axios.get( '...api/api/...', {
},{
headers:headers,
})
.then((response) => {
if(response.status < 300){
dispatch(isLoadingCollegeDashList(false))
dispatch(collegeDashList(response))
console.log(response);
}
else{
response.json().then((responseJSON) => {
console.log("responseJSON",responseJSON);
dispatch(isLoadingCollegeDashList(false))
dispatch(collegeDashListFail(responseJSON.message))
})
}
})
.catch((error) => {
console.log("error",error);
dispatch(isLoadingCollegeDashList(false))
dispatch(collegeDashListFail(error))
})
}
}
export const isLoadingCollegeDashList = (bool) => {
return{
type:'IS_LOADING_COLLEGE_DASH_LIST',
isLoadingCollegeDashList:bool
}
}
export const collegeDashList = (userData) => {
return{
type:'COLLEGE_DASH_LIST',
userData
}
}
export const collegeDashListFail = (error) => {
return{
type:'COLLEGE_DASH_LIST_FAIL',
error
}
}
here's action that im calling if you want to check it
const mapDispatchToProps = dispatch => ({
populateCollege : (token) => dispatch(actions.populateCollege({token}))
});
PS I've for now stored token in the state of one hence passing the token from this dispatch itself.
Let me know if you need any clarification / more information then do let me know. Thanks in advance
Make sure you have the authorisation schema before your token. The schema can be like Basic, Bearer or any other value based on your authorisation details. (eg. Authorization: Bearer TOKEN).
Also, try to reuse your auth headers while creating the axios instance so you won't need to inject them on every call.

Axios not setting data

I'm trying to set data from an axios response but it seems to me like "this" is only in the scope of the axios function. I have tried different variations of the same code that I've seen on other posts, but none are working.
data: () => ({
storeKey: 'dayspanState',
calendar: Calendar.months(),
readOnly: false,
defaultEvents: [],
ticket_event: [],
}),
created(){
this.get_tickets();
console.log(this.ticket_event);
},
methods:
{
get_tickets(){
axios.get('/api/get_patching_tickets')
.then(function (response) {
this.ticket_event = response.data;
}.bind(this));
},
}
Second trial
created(){
var self = this;
axios.get('/api/get_patching_tickets')
.then(function (response) {
self.ticket_event = response.data;
});
console.log(this.ticket_event);
}
Any help would be appreciated.
Try rewriting your function like:
created(){
axios.get('/api/get_patching_tickets')
.then((response) => {
this.ticket_event = response.data;
}).finally(() => {
console.log(this.ticket_event);
});
/* WARNING: the following console will not work as expected
as the local value is set after the successful call
while this is fired immediately after created is called
*/
console.log(this.ticket_event);
}
The callbacks you passed to .then in axios.get are fine. I see the only problem with your code is that it logs this.ticket_event right after calling this.get_tickets() - an asynchronous operation, so it'll not log the updated value after the api call finish because this.get_tickets() operates asynchronously:
this.get_tickets(); // is an async operation
console.log(this.ticket_event); // will not get the most updated value of this.ticket_event
Try this to see if it works:
data() {
return {
storeKey: 'dayspanState',
calendar: Calendar.months(),
readOnly: false,
defaultEvents: [],
ticket_event: [],
}
},
methods: {
get_tickets() {
return axios.get('/api/get_patching_tickets')
.then(response => {
this.ticket_event = response.data;
});
}
},
created() {
this.get_tickets().finally(() => {
console.log(this.ticket_event);
});
}

Parameter pass from one api to another in react-native

I want to pass a parameter value from one API-Request to 2nd API-request so that 2nd api display result accordingly: Here is my function componentWillMount:
componentWillMount() {
axios.post('https://APISITE/api/Auth/AuthorizeByApplication?applicationId=b72fc47a-ef82-4cb3-8179-2113f09c50ff&applicationSecret=e727f554-7d27-4fd2-bcaf-dad3e0079821&token=cd431b31abd667bbb1e947be42077e9d')
.then((response) => { console.log(response.data); });
axios.get('https://APISITE//api/Stock/GetStockItems',
{
params: {
keyWord: 454534534543,
locationId: '',
entriesPerPage: 100000,
pageNumber: 1,
excludeComposites: true,
//add other params
},
headers:
{ Authorization: 'asdfasdsfdfdfdfsfsdxxx'
}
//}).then((response) => { console.log(response.data); });
}).then((response) => this.setState({ products: response.data }));
axios.get('https://APISITE//api/Stock/GetStockLevel', {
params: {
stockItemId: '2f80b45c-85ff-449b-9ad6-ffcc4bb640dd',
},
headers:
{ Authorization: 'asdfasdsfdfdfdfsfsdxxx'
}
// }).then(response => console.log(response));
}).then((response) => this.setState({ racks: response.data }));
}
Value in stockItemId is passed as static value and result displayed in console correctly. How can get stockItemId's value dynamically from 1st-api request?
Edit: Below is data result screenShots of passing stockItemId directly in api and getting from 1st api.
Getting from 1st api: stockItemId: stockItems.data.StockItemId : http://prntscr.com/i7k0j7
Directly passing value of stockItemId screenshot- stockItemId: '2f80b45c-85ff-449b-9ad6-ffcc4bb640dd' http://prntscr.com/i7jyq7
You need to handle the response data from within the then functions.
Notice the way the response from each request is passed into the following then where it can easily used.
componentWillMount() {
axios
.post('https://APISITE/api/Auth/AuthorizeByApplication?applicationId='app id'&applicationSecret='app secret'&token='app token'')
.then((authData) => {
console.log(authData.data);
return axios.get('https://APISITE//api/Stock/GetStockItems', {
params: {
keyWord: 5055967419551,
locationId: '',
entriesPerPage: 100000,
pageNumber: 1,
excludeComposites: true,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
})
})
.then((stockItems) => {
this.setState({ products: stockItems.data })
return axios.get('https://APISITE//api/Stock/GetStockLevel', {
params: {
stockItemId: stockItems.data.stockItemId,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
})
})
.then((stockLevel) =>
this.setState({ racks: stockLevel.data })
)
}
(This code is untested!)
First thing never use componentWillMount component life cycle method to set the component state or call any api request for these purpose use componentDidMount for more reading which life cycle use for which purpose read this article and Secondly just add the second api request inside the first api request response with different name response name as given below:
componentDidMount() {
axios.post('https://APISITE/api/Auth/AuthorizeByApplication?
applicationId='app id'&applicationSecret='app secret'&token='app token'')
.then((responseFirst) => {
axios.get('https://APISITE//api/Stock/GetStockItems', {
params: {
keyWord: 5055967419551,
locationId: '',
entriesPerPage: 100000,
pageNumber: 1,
excludeComposites: true,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
}).then((responseSecond) => this.setState({ products: responseSecond.data }));
axios.get('https://APISITE//api/Stock/GetStockLevel', {
params: {
stockItemId: responseFirst.data.stockItemId,
},
headers: {
Authorization: '0f32ae0d-c4e0-4aca-8367-0af88213d668'
}
}).then((responseThird) => this.setState({ racks: responseThird.data }));
});
}
if you are using redux then read redux documentation to handle async type actions and how to handle it.