Well, I have the same problem. When I create a petition with axios it works properly, but when I have nested axios petitions the page refreshes automatically. And I can't figure out what is the problem.
I am using evt.preventDefault() and return false; but none of them seem work.
When I call this single function everything works fine:
addSport(payload) {
const path = 'http://localhost:5000/sports';
axios.post(path, payload)
.then(() => {
this.getSports();
this.message = 'Sport Added!';
this.showMessage = true;
return false;
})
.catch((error) => {
// eslint-disable-next-line
console.error(error);
});
return false;
}
and I call it:
this.uploadImage(formData, this.addSports, payload);
But, when I try to use this one, the page is reloading after two calls are executed:
uploadImage(formData, callback, payload) {
const path = 'http://localhost:5000/upload';
axios.post(path, formData)
.then((response) => {
callback({
sport_id: payload.sport_id,
name: payload.name,
logo_url: response.data.logo_url,
});
return false;
})
.catch((error) => {
// eslint-disable-next-line
console.error(error);
});
return false;
},
addSport(payload) {
const path = 'http://localhost:5000/sports';
axios.post(path, payload)
.then(() => {
this.getSports();
this.message = 'Sport Added!';
this.showMessage = true;
return false;
})
.catch((error) => {
// eslint-disable-next-line
console.error(error);
});
return false;
}
The way I call it is:
this.uploadImage(formData, this.updateDeporte, payload);
Can anyone help me to figure out how can I fix that?
Related
In my header component:
signIn() {
signInWithPopup(auth, provider).then((result) => {
this.updateUser(result.user.uid);
const userRef = doc(db, 'users', result.user.uid);
this.firestoreUser(userRef)
.then((userDoc) => {
if (!userDoc.exists()) {
this.addNewUserToFirestore(userRef, result.user);
}
})
.then(() => {
console.log('Read user from firestore');
// FIXME: readUserFromFirestore still isn't finishing before moving on...
this.readUserFromFirestore();
})
.then(() => {
console.log('Read personal patches');
this.readPersonalPatches();
})
.then(() => {
console.log('Add watcher');
this.geolocationId = navigator.geolocation.watchPosition(
this.nearLandmark,
this.errorCallback
);
});
});
},
readUserFromFirestore:
async readUserFromFirestore({ commit, state }) {
const userRef = doc(db, 'users', state.user);
try {
const userDoc = await getDoc(userRef);
await (() => {
return new Promise((resolve) => {
for (const property in userDoc.data()) {
const propertyValue = userDoc.data()[property];
commit('addProfileProperty', {
propertyName: property,
propertyValue,
});
}
console.log(
'Just finished putting in user patches',
state.profile.patches
);
resolve();
});
})();
} catch (e) {
alert('Error!');
console.error(e);
}
},
};
readPersonalPatches:
async readPersonalPatches({ commit, state }) {
try {
if (state.user) {
// Get a copy of all the user's patches
state.ownedPatchesArray = [];
state.unownedPatchesArray = [];
await (function () {
console.log('Made it inside the await from readpersonalpatches');
return new Promise((resolve) => {
console.log('raw badges', state.rawPatches);
console.log('user badges', state.profile.patches);
state.rawPatches.forEach((patch) => {
if (JSON.stringify(state.profile.patches).includes(patch.slug)) {
commit('addToArray', {
arr: 'ownedPatchesArray',
value: patch,
});
} else {
commit('addToArray', {
arr: 'unownedPatchesArray',
value: patch,
});
}
});
resolve();
});
})();
}
} catch (error) {
alert('Error reading personal patches');
console.log(error);
}
},
Console Output:
Read user from firestore
Read personal patches
Made it inside the await from readpersonalpatches
raw badges **accurate badge list**
user badges undefined
TypeError: Cannot read properties of undefined (reading 'includes')
Add watcher
Just finished putting in user patches **accurate user patch list**
In readUserFromFirestore I wasn't sure exactly how to approach waiting on the user's patches to be added to the array before moving on in the sign-in process. One of the properties that is being looped over is profile.patches. readPersonalPatches() uses that property. But on fresh logins I get an error in readPersonalPatches() because profile.patches is undefined at that point. (On logins after cacheing I do not have an issue reading profile.patches apart from the data potentially being outdated.)
I am using Vue, Vuex, and Firebase for Authentication and Firestore.
For my purposes patch and badge are interchangeable terms.
Thanks to Luaan for educating me on how then blocks work I have it going now. I wasn't returning the promises, only calling the function and then not doing anything with the returned promises 🤦
Fixed lines:
.then((userDoc) => {
return (function () {
if (!userDoc.exists()) {
this.addNewUserToFirestore(userRef, result.user);
}
})();
})
.then(() => {
console.log('Read user from firestore');
return this.readUserFromFirestore();
})
.then(() => {
console.log('Read personal patches');
return this.readPersonalPatches();
})
I'm trying to get the error response from my Vue store dispatch method, into my component, so I can tell the user if the save failed or not.
store/userDetails.js
const state = {
loading: {
user_details: false,
}
}
const getters = {
// Getters
}
const actions = {
save({commit, dispatch, rootState}, payload) {
commit('setLoading', {name: 'users', value: true});
axios(
_prepareRequest('post', api_endpoints.user.details, rootState.token, payload)
).then((response) => {
if (response.data) {
commit('setState', {name: 'user_details', value: response.data.units});
commit('setLoading', {name: 'user_details', value: false});
dispatch(
'CommonSettings/setSavingStatus',
{components: {userDetails: "done"}},
{root:true}
);
}
}).catch((error)=> {
console.log(error)
return error
}
)
}
My component method
views/Users.vue
send() {
this.$store.dispatch({
type: 'Users/save',
userDetails: this.current
}).then(response => {
console.log(response)
});
},
Above, I'm logging out the response in two places.
The response in my store/userDetails.js file is logged out fine, but it's not being passed to my send() function in my component - it comes up as undefined. Any reason why it wouldn't be passed through? Is this the correct way to do this?
This works for me. Try this solution.
store.js
actions: {
save(context, payload) {
console.log(payload);
return new Promise((resolve, reject) => {
axios(url)
.then((response) => {
resolve(response);
})
.catch((error) => {
reject(error);
});
});
},
},
My Component method
App.vue
save(){
this.$store.dispatch("save", dataSendToApi).then((response)=>{
console.log(response)
})
}
Try returning axios call in the Store Action:
// add return
return axios(
_prepareRequest('post', api_endpoints.user.details, rootState.token, payload)
)
.then() // your stuff here
.catch() // your stuff here
If that won't work, use Promise in the Store Action. Like this:
return new Promise((resolve, reject) => {
return axios() // simplify for readibility reason, do your stuff here
.then((response) => {
//... your stuff here
resolve(response) // add this line
})
.catch((error) => {
// ... your stuff here
reject(error) // add this line
})
})
you should return a promise, reference link:vue doc
My goal is to test my function: fetchStats
Expected Results: It console.logs the error and a failure message. and sets _isFetching to false.
Actual Results: The error is caught but console.logs not fired and isFetching is not set.
Code below:
fetchStats:
fetchStats() {
this._isFetching = true;
// fetch stats after building url and replacing invalid characters
return new Promise(async (resolve, reject) => {
await API.fetchStats(this.rsn)
.then(jres => {
this.skills = jres.main.skills;
this._isFetching = false;
resolve('success');
})
.catch(err => {
console.log(err);
console.log('error retreiving stats');
this._isFetching = false;
reject('Failed to retreive stats');
})
.finally(() => {
this._isFetching = false;
});
});
}
The test:
it("catches thrown errors", () => {
this.apiFetchStats.throws(new Error());
const player = Player.fromJSON(
JSON.stringify({
rsn: 'rsn',
skills: {
overall: { level: 2000 },
attack: { attack: {} },
defence: { defence: {} },
},
})
);
sinon.spy(console, "log");
player.fetchStats();
expect(this.apiFetchStats).to.be.calledOnce;
expect(this.apiFetchStats).to.have.thrown();
expect(console.log).to.have.been.calledTwice;
expect(player.isFetching()).to.be.false;
console.log.restore();
});
});
The first two expects pass fine, signalling that it has been called and did throw so it should be in catch block but console.log was not called and isFetching was not set. Does anyone have an idea on what is going wrong?
Resolved by adding expectations to .then of player.fetchStats like so:
player.fetchStats().then(() => {
expect(this.apiFetchStats).to.be.calledOnce;
expect(this.apiFetchStats).to.have.thrown();
expect(console.log).to.have.been.calledTwice;
expect(player.isFetching()).to.be.false;
})
.finally(() => { console.log.restore(); });
I have a Vue-App which runs with Vuex and Axios. In this app I have vuex-store which handles API-calls, but a problem is that when I call the store-actions I cant chain the response in the caller.Any ideas what Im doing wrong?
Calling code:
import { FETCH_PRODUCTS, ADD_PRODUCT } from './actions.type'
methods: {
sendNewProduct () {
this.$store
.dispatch(ADD_PRODUCT, this.newProductForm)
.then(() => {
console.log('This never gets called')
})
}
}
Vuex-store:
const actions = {
[ADD_PRODUCT] (context, credentials) {
return new Promise((resolve) => {
ApiService
.post('/Products/', {
Name: credentials.Name,
Description: credentials.Description,
Price: credentials.Price
})
.then(({ data }) => {
this.$store
.dispatch(FETCH_PRODUCTS)
resolve(data)
})
.catch(({ response }) => {
console.log(response)
context.commit(SET_ERROR, 'Error adding product')
})
})
}
}
const actions = {
[ADD_PRODUCT](context, credentials) {
return ApiService.post("/Products/", {
Name: credentials.Name,
Description: credentials.Description,
Price: credentials.Price
})
.then(({ data }) => {
this.$store.dispatch(FETCH_PRODUCTS);
return data;
})
.catch(({ response }) => {
console.log(response);
context.commit(SET_ERROR, "Error adding product");
throw new Error("Error adding product");
});
}
};
I've removed the new Promise(...) because axios already creates a promise.
If added a return data in the then callback and a throw in the catch callback to let the calling api receive the data/error.
Note that the promise resolves before the FETCH_PRODUCTS completes, to make sure that action is also completed, you'd write:
.then(({ data }) => {
return this.$store.dispatch(FETCH_PRODUCTS)
.then(() => data);
})
I'm trying to create new resource with redux form and REST api.
I dispatch createPost action and I want to check if the post was succeeded before continue.
const handleFormSubmit = (values, dispatch) => {
dispatch(createPost(values));
//I want to check here if post was succeeded.
//if status = 200 this.props.history.push('/');
}
export function createPost(values) {
return async function(dispatch) {
let request;
try {
request = await axios.post(`${ROOT_URL}/posts`, values)
} catch(err) {
request = { err };
}
dispatch({
type: CREATE_POST,
payload: request
})
}
}
Return a promise, something like this :
export function createPost(values) {
return function(dispatch) {
return new Promise( async function(resolve, reject){
let request;
try {
request = await axios.post(`${ROOT_URL}/posts`, values)
} catch(err) {
reject(err)
}
dispatch({
type: CREATE_POST,
payload: request
})
resolve(request)
})
}
}
const handleFormSubmit = () => {
dispatch(createPost(values))
.then( res => {
// do yoour stuff on succes
} )
.catch(err => {
// stuff on err
})
}
As seeing your codes, I don't think you need to use promise.
Please try like following:
const getAction = (values) => (dispatch) => {
return axios
.post(`${ROOT_URL}/posts`, values)
.then(
() => {
dispatch({
type: CREATE_POST,
payload: request
})
},
() => {
throw new SubmissionError({
_error: 'Failed'
});
}
);
};
const handleSubmit = (values) => {
return dispatch(getAction(values));
};