Axios get inside a .then is not working as intended - reactjs

I am using axios to make a http request. Inside the .then() i am using another axios call. Finally, I have a third then() which is supposed to run after the second then but it is actually not doing so.
let assets = [];
export const initAssets = () => {
return dispatch => {
dispatch(setLoadingToTrue());
axios.get('https://....json')
.then(response => {
for(let key in response.data) {
assets.push(response.data[key]);
}
})
.then(() => {
const token = '...';
assets.forEach((cur) => {
axios.get('...' + cur.ticker + '/quote?token=' + token)
.then(response => {
console.log(response);
cur.price = response.data.latestPrice;
})
})
})
.then(() => {
dispatch(initAllAssets(assets));
dispatch(setLoadingToFalse());
})
.catch(error => {
console.log(error);
dispatch(setLoadingToFalse());
})
}
}
The dispatch on the last .then are being executed before the axios request in the second then is completed. How can I make the last then run only after the second axios request is completed?

You can make use of Promise.all to return the response to next .then block and it will be called once all the promises have resolved in the second .then
let assets = [];
export const initAssets = () => {
return dispatch => {
dispatch(setLoadingToTrue());
axios.get('https://....json')
.then(response => {
for(let key in response.data) {
assets.push(response.data[key]);
}
})
.then(() => {
const token = '...';
const promises = [];
assets.forEach((cur) => {
promises.push(axios.get('...' + cur.ticker + '/quote?token=' + token)
.then(response => {
console.log(response);
cur.price = response.data.latestPrice;
}))
})
return Promise.all(promises);
})
.then(() => {
dispatch(initAllAssets(assets));
dispatch(setLoadingToFalse());
})
.catch(error => {
console.log(error);
dispatch(setLoadingToFalse());
})
}
}

Related

run useEffect an other time when my function is called

I'm using useEffect to get all that I want from my backEnd,
When an onChange event is triggered, I call my function checkHandler method, where I make a post request to my backend. But the Get that I do first is not actualized, and the only way that I found to show the good stuff is to reload the page :s I think there is a better way to do it if my useEffect renders another time, but I don't know how to do it
const [message, setMessage] = useState([]);
useEffect(() => {
axios
.get(getAllMessage, config)
.then((res) => {
setMessage(res.data);
console.log("mounted");
})
.catch((err) => {
console.log(err);
});
}, []);
const checkHandler = (e) => {
let item = e.target.closest("[data-id]");
const disLikeMessage = `http://localhost:3001/api/like/dislike/${item.dataset.id}`;
const likeMessage = `http://localhost:3001/api/like/${item.dataset.id}`;
if (!item.checked) {
console.log("unchecked");
axios
.post(disLikeMessage, {}, config)
.then((res) => {})
.catch((err) => {
console.log(err);
});
} else {
console.log("checked");
axios
.post(likeMessage, {}, config)
.then((res) => {})
.catch((err) => {
console.log(err);
});
}
};
You don't need to refresh useEffect as there is no concept to refresh useEffect
Create a method that will fetch your all messages
const fetchMessages = () => {
axios
.get(getAllMessage, config)
.then((res) => {
setMessage(res.data);
console.log("mounted");
})
.catch((err) => {
console.log(err);
});
};
Inside your useEffect callback just call this fetchMessages()
useEffect(() => {
fetchMessages();
}, []);
Here is your checkHandler()
const checkHandler = (e) => {
let item = e.target.closest("[data-id]");
const disLikeMessage = `http://localhost:3001/api/like/dislike/${item.dataset.id}`;
const likeMessage = `http://localhost:3001/api/like/${item.dataset.id}`;
fetchMessages(); // Call fetchMessages wherever you need to fetch all messages
if (!item.checked) {
console.log("unchecked");
axios
.post(disLikeMessage, {}, config)
.then((res) => {})
.catch((err) => {
console.log(err);
});
} else {
console.log("checked");
axios
.post(likeMessage, {}, config)
.then((res) => {})
.catch((err) => {
console.log(err);
});
}
};

async function in react component isn't working when triggered from the axios request

network.services.js
axiosCall = (axiosURL) => {
// const axiosURL = "https://api.github.com/user"
axios.get(axiosURL, {
headers: {
'Authorization': `qwdvryjutmnevw`,
}
}).then((res) => {
console.log(res.data);
return res.data;
}).catch((error) => {
throw error.message;
// console.error(error);
// toast.error(error.message);
})
}
component.js
const getData = async () => {
const asyncExample = async () => {
const result = await networkServices.axiosCall("/api/v1/calendars");
const responseData = await result;
console.log(responseData);
return responseData;
}
const data = asyncExample()
data.then(function(result) {
console.log(result); // "Some User token"
})
}
Trying to get data from service to my component in const result, console form service is consoling data but component is always returning undefined instead of data from the service file. SetTimeout function is also not working in component.
You have many mistakes. I advise you to take a look at documentation about Promises
First one:
You don't return data in axiosCall
A way to return data:
axiosCall = (axiosURL) => new Promise((resolve, reject) => {
axios.get(axiosURL, {
headers: {
'Authorization': `yourTokenHere`,
}
}).then((res) => {
// return a response data
resolve(res.data);
}).catch((error) => {
// return only error message
reject(error.message);
})
})
to use axiosCall:
try {
// don't forgot to configure axios with base url
const data = await axiosCall('/api/v1/calendars');
// do something with your data
} catch (e) {
// do something with error message
console.log(e);
}
Second:
Your make mistakes when call async function
Look at this example:
const getData = () => {
networkServices
.axiosCall("/api/v1/calendars")
.then(function(result) {
// when promise resolve
console.log(result);
})
.catch(error => {
// when promise reject
console.log(error)
})
}

call function synchronously in reactjs

I want to call function only after previous function gets executed. I tried with promises but its not working,I also tried with async await but the last function is getting executed.After execution of first function its state value i want to pass to next function and so on.Please help me in this.Thanks in advance.
handleAllFunctionsOnClickPayLater() {
let promise = Promise.resolve();
promise
.then(() => this.handleGuestLogin())
.then(() => setTimeout(this.handleAddress(),1000))
.then(() => setTimeout(this.handlePayLater(),2000))
}
handleGuestLogin() {
const UserDetails = {
name: this.state.name,
email: this.state.email,
mobile: this.state.number
}
fetch(api,{
method : 'POST',
body: JSON.stringify(UserDetails)
})
.then(res => res.json())
.then(data => {
return this.setState({
cid: data.Data.cid
},() => {console.log(this.state.cid)})
})
}
handleAddress() {
var address_details = {
cid:this.state.cid
...other details
}
fetch(api,{
method : 'POST',
body: JSON.stringify(address_details)
})
.then(res => res.json())
.then(data => {
console.log("address added in db customer_address",data);
return this.setState({
address_id: data.address_id,
})
}
handlePayLater = () => {
var bookingDetails = {
cid: this.state.cid,
address_id: this.state.address_id
}
fetch(api,{
method : 'POST',
body : JSON.stringify(bookingDetails)
})
.then(res => res.json())
.then(data => {
return this.setState({bookingId:data.booking_id});
}
Assuming handleAddress, handleGuestLogin and handlePayLater return promises, you can use an async/await function
synchronousPromises = async () => {
try {
const handleGuestLoginResult = await this.handleGuestLogin();
const handleAddressResult = await this.handleAddress();
const handlePayLaterResult = await this.handlePayLater();
} catch (error)
{
return reject(error); //will cause .catch to fire
}
return resolve([
handleGuestLoginResult,
handleAddressResult,
handlePayLaterResult
]); //will cause .then to fire
}
since synchronousPromises is an async function, it itself returns a promise. to use it, you can call it as
callSyncronousPromises = () => {
synchronousPromises()
.then(success => {
//handle success
})
.catch(error => {
//handle error
}
}

Nested fetch/then methods

I am using the flickr API to search images and I would like to get photos with theirs tags at same time.
To do it, I need first to use flickr.photos.search method to fetch the photo_id and build the photo url (1st and 2nd 'then' methods). In the 3th 'then' part I used another API method flickr.photos.getInfo to get the tags for each photo and finally return urlPhoto and tagsInfo like json.
The problem is that tagsInfo variable continues been a promise and I can not render the tags (array) of the photo. However, urlPhoto has a correct value.
export function fetchAll(...) {
return fetch(BASE_URL + encodeGetParams(params1), options)
.then(response => {
return response.json();
})
.then((data) => {
return data.photos.photo.map(e =>
({
"photo_id": e.id,
"urlPhoto": 'https://farm'+e.farm+'.staticflickr.com/'+e.server+'/'+e.id+'_'+e.secret+'.jpg',
})
)
})
.then((data) => {
return data.map(e => {
const url = BASE_URL + encodeGetParams({ ...params2, "photo_id": e.photo_id });
const tagsInfo = fetch(url, options)
.then(data => data.json())
.then(data => data.photo.tags.tag.map(e => e._content));
return {
"urlPhoto": e.urlPhoto,
"tagsInfo": tagsInfo
}
}
)
})
}
You could create a separate promise for each element in the array, use Promise.all on those promises and return that.
export function fetchAll(/* ... */) {
return fetch(BASE_URL + encodeGetParams(params1), options)
.then(res => res.json())
.then(data => {
const promises = data.photos.photo.map(e => {
const result = {
urlPhoto: `https://farm${e.farm}.staticflickr.com/${e.server}/${e.id}_${e.secret}.jpg`
};
const url = BASE_URL + encodeGetParams({ ...params2, photo_id: e.photo_id });
return fetch(url, options)
.then(res => res.json())
.then(data => {
result.tagsInfo = data.photo.tags.tag.map(e => e._content);
return result;
});
});
return Promise.all(promises);
});
}
Do you not just need to return the last fetch and add an extra .then that would resolve to
{
"urlPhoto": e.urlPhoto,
"tagsInfo": tagsInfo
}
like
export function fetchAll(...) {
return fetch(BASE_URL + encodeGetParams(params1), options)
.then(response => {
return response.json();
})
.then((data) => {
return data.photos.photo.map(e =>
({
"photo_id": e.id,
"urlPhoto": 'https://farm'+e.farm+'.staticflickr.com/'+e.server+'/'+e.id+'_'+e.secret+'.jpg',
})
)
})
.then((data) => {
return data.map(e => {
const url = BASE_URL + encodeGetParams({ ...params2, "photo_id": e.photo_id });
return fetch(url, options)
.then(data => data.json())
.then(data => data.photo.tags.tag.map(e => e._content))
.then(tagInfo => {
return {
"urlPhoto": e.urlPhoto
"tagsInfo": tagsInfo
}
})
}
)
})
}
What you're currently doing is returning the urlPhoto/tagsInfo before the tagsInfo fetch promise has resolved so an extra then should fix it!

How to update the page after call Axios Successful ? React

so I'm doing a project that uses Axios with Json-server, but I have a problem, every time I do a Patch, I have to give F5 on the homepage for it to update, I wanted know how I could do it so that it did not happen, and automatically.
My Patch:
onSubmitDate = event => {
const newUrl = prompt("Please with new URL:");
const personCurrent = event.target.value;
axios.patch(`http://localhost:3004/employee/${personCurrent}`, {
url_git: newUrl
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
My Get:
componentDidMount() {
axios
.get("http://127.0.0.1:3004/employee")
.then(response => this.setState({ employee: response.data }));
}
Someone would can help me?
I am assuming the update is on the component you are handling.
For you to create a re-render of your component, you can simply set the state. See more here
What is the format of your response? Does it include the updated data you wish to display? If that is the case, it's easy, simply do a setState in your then:
onSubmitDate = event => {
const newUrl = prompt("Please with new URL:");
const personCurrent = event.target.value;
axios.patch(`http://localhost:3004/employee/${personCurrent}`, {
url_git: newUrl
})
.then(response => {
console.log(response);
this.setState({employee: response.data})
})
.catch(error => {
console.log(error);
});
}
If the response is not providing the data you want updated in your component, your can simply do your GET of whatever data you want in the then of your PATCH and set the state on it's response. So something like this:
onSubmitDate = event => {
const newUrl = prompt("Please with new URL:");
const personCurrent = event.target.value;
axios.patch(`http://localhost:3004/employee/${personCurrent}`, {
url_git: newUrl
})
.then(response => {
console.log(response);
axios.get("http://127.0.0.1:3004/employee")
.then(response => this.setState({ employee: response.data }));
})
.catch(error => {
console.log(error);
});
}

Resources