Vuex promise reject returns undefined - vue.js

I want the promise reject to return the error to my method but the response is empty inside my methods then() function, how can i get the error response to be returned to my method for further use or even inside the catch function.
My vuex action
//authAction
login({ commit }, payload) {
new Promise((resolve, reject) => {
user.login(payload.user.email, payload.user.password)
.then(response => {
const user = response.data.user;
// If there's user data in response
if (user) {
const payload = [user]
commit('AUTH_SUCCESS', payload, { root: true })
resolve(response)
} else {
reject({ message: "Sorry, cant login right now" })
}
})
.catch(error => {
console.log(error.response.status)
reject(error)
})
})
}
My method
// Login method
login() {
if (!this.checkLogin()) return;
this.$vs.loading();
const payload = {
checkbox_remember_me: this.checkbox_remember_me,
user: {
email: this.email,
password: this.password
}
};
this.$store
.dispatch("auth/login", payload)
.then(res => {
this.$vs.loading.close();
console.log(res);
})
.catch(error => {
this.$vs.loading.close();
this.$vs.notify({
title: "Error",
text: error.message,
});
});
}
What am i missing?
Thanks in advance!

My solution is to 1. dispatch an action whenever an error is thrown which updates state 2. watch state change in view and do something with it

Related

blink store data after change route

how can i avoid the data blink after update store data?
you can see the effect here:
https://drive.google.com/file/d/178raL6AJiC4bpIOImnaTKh6Yf9GruTCz/view?usp=sharing
component:
[...]
mounted() {
this.getIdeasFromBoard(this.$route.params.board_id);
},
[...]
store:
[...]
const actions = {
getIdeasFromBoard({ commit, dispatch }, board_id) {
apiClient
.get('/ideas/' + board_id)
.then((result) => {
console.log('success');
commit("SET_IDEAS_BOARD", result.data);
})
.catch(error => {
console.log('error' + error);
alert("You have failed to log in. Try again with another credentials.");
dispatch('auth/logout', null, { root: true });
this.$router.push({ name: "public" });
});
},
[...]
i've searched some simple tutorial about consuming api with error handling, but didnt find it.
thanks
It's because IDEAS_BOARD has the previous data until the new API call is completed. You would need to display a loader or a blank screen until the API call for the selected board is completed.
From actions, return a promise so that your component knows when is the call completed.
getIdeasFromBoard({ commit, dispatch }, board_id) {
return new Promise((resolve, reject) => {
apiClient
.get('/ideas/' + board_id)
.then((result) => {
console.log('success');
commit("SET_IDEAS_BOARD", result.data);
resolve()
})
.catch(error => {
console.log('error' + error);
alert("You have failed to log in. Try again with another credentials.");
dispatch('auth/logout', null, { root: true });
this.$router.push({ name: "public" });
reject()
});
})
},
In your .vue component,
async mounted () {
this.loading = true // some flag to display a loader instead of data
await this.$store.dispatch()
this.loading = false
}
There must be some other ways too like having this loading flag in the Vuex store. But it depends on you

React Native AsyncStorage.getItem is not working. ({"_40": 0, "_55": null, "_65": 0, "_72": null})

Good day! I have this function of AsyncStorage that gets an item of a token. I used with ApolloClient to process the token but when I test it first, it seems to have an error with what will I get by AsyncStorage function.
export function jwtLogin(data) {
return async dispatch => {
const userData = {
email: data.email,
password: data.password,
};
console.log(userData);
const client = new ApolloClient({
link: new HttpLink({
uri: API_URL,
}),
cache: new InMemoryCache(),
});
client
.mutate({
mutation: loginUser,
variables: {
email: userData.email,
password: userData.password,
},
})
.then(resp => {
console.log(resp.data.tokenCreate);
console.log('Token', resp.data.tokenCreate.token);
if (resp.data.tokenCreate.token !== null) {
saveJWTTokenData(resp.data.tokenCreate.token); //from AsyncStorage save function
async function main() { //function of AsyncStorage
await AsyncStorage.getItem('jwt_token').then(item => {
return item;
});
}
console.log(main()); // returns error
Actions.push('main_loading');
} else {
const errors = resp.data.tokenCreate.errors;
{
errors.map(err => {
Alert.alert('Error.', err.message);
});
}
}
})
.catch(err => {
Alert.alert('Error.', err.message);
});
};
}
For the save storage function:
export const saveJWTTokenData = async jwt_token => AsyncStorage.setItem('jwt_token', jwt_token);
My Error Log Picture
I think your Promise is not handled correctly..
Try to add a catch after your then call like this:
.catch(err => console.log(err))
Or try to use your function like this maybe:
await getData("jwt_token")
.then(data => data)
.then(value => this.setState({ token: value })) // here it is setState but I guess you can also return
.catch(err => console.log("AsyncStorageErr: " + err));

Passing an error to a component

I have an AddComment.vue component which has a form, on submit it hits a laravel api endpoint where validation happens. If validation fails I want to show the errors in AddComment.vue. How can return the error.response object to AddComment.vue? Currently, I can see 'fired' in the console when I want to be logging the error. Where am I going wrong any help would be greatly appreciated
AddComponent.vue
methods: {
addComment() {
this.$store.dispatch('addComment', {
name: this.name,
email: this.email,
body: this.body
})
.then(response => {
this.$router.push({ name: 'home' })
console.log('fired')
})
.catch(error => {
console.log(error)
})
},
}
store.js
actions: {
addComment(context, comment) {
new Promise((resolve, reject) => {
axios.post('/comments', {
name: comment.name,
email: comment.email,
body: comment.body,
approved: false
})
.then(response => {
context.commit('addComment', response.data)
resolve(response)
})
.catch(error => {
reject(error)
})
});
},
}
The catch() block only gets called if the Laravel backend throws an error. So if you are returning a normal status code of 2xx then axios always calls the .then() part. In that case, you have to resolve the error message yourself.
Try something like this in your backend route (it will return an error):
return response()->toJson([
'message' => 'error message',
], 500);
And see if this responds with an actual error in you vuejs application.

How to update view inside axios promise and after store dispatch?

I have a simple vue app where I'm trying to add simple authentication. Inside my login.vue, I use axios to authenticate the user via ajax and store the token returned by the api in the store then redirect to a new page (ex: dashboard.vue).
The problem is that the token is saved but the view is not updated, can't call router.push() ...
Any ideas why isn't it working ? Thanks
Login.vue
methods: {
authenticate () {
var dataLogin = {
email: this.login,
password: this.password
}
var headers = { headers: { 'Content-type': 'application/json', 'Accept': 'application/json' } }
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
this.$store.dispatch('login', response.data).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})
}
}
The store function just save the token with localStorage
const actions = {
login (context, data) {
context.commit('authenticate', data)
}
}
const mutations = {
authenticate (state, data) {
localStorage.setItem('user-access_token', data.access_token)
}
}
You are calling a then() handler when you dispatch the action.
But your action does not return a promise.
So return a promise in your action as follows:
const actions = {
login (context, data) {
return new Promise((resolve, reject) => {
context.commit('authenticate', data)
resolve()
})
}
}
Also chain your promises for better readability
axios.post(config.apiUrl, dataLogin, headers)
.then(response => {
return this.$store.dispatch('login', response.data)
}).then(() => {
// if there is no error go to home page
if (!this.$store.getters.error) {
this.$router.push('/')
}
})
.catch(error => {
this.errorMessage = error.response.data.message
this.authError = true
})

Triggering a route only after dispatch and commit completed in VueJS

I do have a form submit which takes email and password then pass them into an action in store called userSignIn
SignIn.vue :
onSubmit () {
if (this.$refs.form.validate()) {
const user = {
email: this.email,
password: this.password
}
this.$store.dispatch('userSignIn', user)
.then(() => {
this.$router.push('/')
}).catch(err => {
console.log(err)
})
}
}
Within store, I do have a userSignIn action like this
store.js actions:
userSignIn ({commit, getters}, payload) {
getters.Api.post(`user/signin`, {
email: payload.email,
password: payload.password
}).then(res => {
commit('userSignIn', res.data.token)
}).catch(err => {
console.log(err)
})
}
The routing(this.$router.push('/')) should only be done after userSignIn commit(commit('userSignIn', res.data.token)). But what actually happening routing triggers before commit, which results and error because user token is not set yet.
How to trigger something(in this case this.$router.push('/')) only after completion of dispatch and commit within it?
Returning the promise did the trick.
userSignIn ({commit, getters}, payload) {
return getters.Api.post(`user/signin`, {
......
})