Access vuex store from catch block - vue.js

Im trying to put error messages from an api call and put it in the vuex store, but im not sure how to do it.
I have this in a "method" within a vue file
axios
.post("/api/model", this.model)
.then(response => {
window.location.href = "/Home/Index";
})
.catch(function(error) {
if (error.response) {
this.$store.commit("setServerErrors", error.response.data);
}
});
Im getting the following error:
Uncaught (in promise) TypeError: Cannot read property '$store' of undefined

Probably your function is reassigning the value of this.
Try changing it to:
axios
.post("/api/model", this.model)
.then(response => {
window.location.href = "/Home/Index";
})
.catch(error => { // <= HERE IS THE CHANGE!!
if (error.response) {
this.$store.commit("setServerErrors", error.response.data);
}
});
Read about the difference between function(arg) {}and (arg) => {}here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

You are using a function instead of an arrow function on the catch block so this inside that block has a different scope.
Just replace the function with an arrow function.
axios
.post("/api/model", this.model)
.then(response => {
window.location.href = "/Home/Index";
})
.catch((error) => {
if (error.response) {
this.$store.commit("setServerErrors", error.response.data);
}
});

Related

Testing Vue with Jest gives an error TypeError: Cannot read property 'then' of undefined

I have been trying to run a test in a file, but I am not even testing the function yet, but I keep getting an error TypeError: Cannot read property 'then' of undefined
The lines in the vue file look like this:
this.$store.dispatch($c.ACTION_FETCHDATA, payloadTradingAccounts).then((response) => {
if (response) {
self.$store.commit(`accounts/${$c.MUTATE_SETACCOUNTS}`, response);
self.isLoading = false;
}
});
and in actions, I got the following:
[$c.ACTION_FETCHDATA]({state, commit, rootState}, payload) {
return new Promise((resolve, reject) => {
let instance = axios.create({
baseURL: $c.DEFAULT_API_URL,
timeout: $c.DEFAULT_TIMEOUT,
headers: {
'X-Session-Token': rootState.accessToken
}
});
instance.get( payload.url, {
params: payload.params
}).then((response) => {
let rows = response.data.data;
resolve(rows);
}).catch((err) => {
onError(err, commit);
console.log(err);
});
});
},

Pass Response Value in Vue Component

i already call the axios and show using console log if it is successful or not already, However i wanted to pass the axios post response value to my vue component and display the response in my vue component in order for me to make a condition. Is there any way to do it? I try some other part but no luck. Kindly guide me.
main.vue
methods: {
onClicked() {
this.$store
.dispatch('Clickme', this.data)
.then(() => {
alert("Success");
})
.catch(() => {
alert("Error");
})
}
}
clicked.js
return new Promise((resolve, reject) => {
clicked(username, password)
.then(resp => {
console.log("---->>>> : ");
const data = resp.data.data
console.log(username, password);
console.log(resp);
console.log("statresponse.status : " + resp.data.status);
console.log("statresponse.message : " + resp.data.message);
console.log("statresponse.inside message : " + resp.data.data.message);
// console.log("USER.JS RESPONSE: " + resp.data.status);
// console.log("USER.JS RESPONSE: " + resp.data.message);
setToken(data.token)
commit('SET_TOKEN', data.token)
resolve()
})
.catch(error => {
console.log(error)
reject(error)
})
})
Try changing main.vue to:
onClicked() {
this.$store
.dispatch('Clickme', this.data)
.then((response) => {
//Do whatever you want with your response
alert("Success");
})
.catch(() => {
alert("Error");
})
}
and change clicked.js to:
resolve(resp.data.data)
This will make so the promise resolves the response data.
However if you make the http request in your store/using vuex, what you probably want to do is commit a mutation to put the response into your state - and then map the state from your component.

Vue returning from a promise

I am trying to return some value from this dispatch
this.$store.dispatch('setValue', this.Value)
.then(response => {
console.log(response)
});
In my vuex action I have
.catch(error => {
if (error.response.status === 412) {
return "some message"
}
});
How can I pass the error back to the .vue file where the vuex dispatch is made?
I think the correct way of doing this is to have a status property in your store.
Your status object would consist out of error, success, loading.
So if your action throw exception you can handle it like this:
catch (error) {
commit("error", `Some Message`);
}
Your error mutation would look like this:
error(state, payload) {
state.status.success = false;
state.status.loading = false;
state.status.error = payload || false;
}
Your template would just listen on the store.state.status
<div v-if="store.state.status.error">{{store.state.status.error}}</div>
I might be wrong but in my personal opinion I feel it is wrong to use actions to return stuff. Your using the store so might as well leverage it best you can.
Other extra benefits is, you can indicate to your .vue file if api is loading or when something is successful.
What I ended up doing was pretty simple. I chained the catch to my dispatch:
this.$store.dispatch('setValue', this.Value)
.then(response => {
console.log(response)
})
.catch(error => {
if (error.response.status === 412) {
return "some message"
}
});
Then I returned the Axios call from the action:
return axios({
method: 'post',
url: `/mypath,
data: mydata,
json: true,
})
This means I could deal with the returned data/errors locally where I wanted to trigger an action.
Store:
.catch(error => {
if (error.response.status === 412) {
throw error
}
});
Vue element with async method:
try{
let response = await this.$store.dispatch('setValue', this.Value)
} catch(error) {
console.log(error)
});

React Native fetch doesn't work in another fetch callback

If I call my api function from POINT 1, fetch method inside the api method works well. When I comment it out and call the function at POINT 2 fetch method inside the addAccount() doesn't work. There is no exception, no rejection, no request on Reactotron, even I can't find request over Charles Proxy. What is the difference and what I have to know to figure it out?
I tried with RN 0.55.2 and 0.57.5
// Auth.js typical react native component
import * as api from '../actions/api';
class Auth extends Component {
// first triggered function
loginAccount(){
// api.addAccount(); // POINT 1 - this line works well if I uncomment
fetch('https://domain-a.com/login/',{
method: 'POST',
credentials: "same-origin",
headers: {
'accept-language': 'en-US;q=1',
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: encodeURIComponent(bodyParameters)
}).then((response) => {
console.log(response);
return response.json()
}).then(({ status, invalid_credentials }) => {
if(status == "ok"){
CookieManager.get('https://domain-a.com')
.then((cookies) => {
this.fetchAccountData(cookies);
})
})
}
fetchAccountData(cookies){
fetch('https://domain-a.com/'+cookies.user_id+'/info/',{
method: 'GET',
headers: {
'cookie': cookies
}
}).then((response) => {
return response.json();
})
.then(({ user, status }) => {
api.addAccount(); // POINT 2 - this line doesn't work
});
}
}
// api.js
// I repleaced fetch code with document example just to be clearify
export const addAccount = () => {
console.log("fetch begin"); // always works
fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson); // won't works from point 2
})
.catch((error) =>{
console.error(error); // never runs
});
}
It looks like your first .then statement in the addAccount() function is missing a return statement. responseJson would be undefined without a proper a 'return response.json()' statement. Also adding brackets for better semantic formatting.
export const addAccount = () => {
console.log("fetch begin"); // always works
fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => {
console.log(response); //test this response
return response.json();
})
.then((responseJson) => {
console.log(responseJson); // won't works from point 2
})
.catch((error) =>{
console.error(error); // never runs
});
}

using fetch with ES2015 modules in Canary

I'm trying out ES2015 modules in Chrome Canary Version 60.0.3102.0. My script.js file reads like this:
import {fetchJSON} from './functions/fetchJSON.js';
const configFile = 'config.json';
const init = () => {
fetchJSON(configFile)
.then((data) => { // code fails here at ln.7
console.log(data);
})
.catch(error => console.log(error));
};
init();
and my fetchJSON.js file reads like this:
export function fetchJSON(url) {
const fetchJSON = fetch(url)
.then(response => response.json())
.then(data => {
console.log(data); // data exists and is reported in the console
return data;
});
}
I'm getting the error:
script.js:7 Uncaught TypeError: Cannot read property 'then' of undefined
at init (script.js:7)
at script.js:14
Your fetchJSON function isn't returning anything. Because of that, when you try chaining a .then on the result of fetchJSON, you're getting the Uncaught TypeError - undefined.
Solution: return your Promise chain in your fetchJSON function:
export function fetchJSON(url) {
return fetch(url)
.then(response => response.json())
.then(data => {
return data;
});
}