Call multiple async functions using useEffect - reactjs

I have the following function that makes a call to the api
useEffect(() => {
loadMarkets();
}, []);
async function loadMarkets() {
const marketInformation = await frService.getMarketInfo();
addMarketInfo(marketInformation.response.data);
}
I want to make a similar call to loadBooks(). If I don't mind which method comes first, would I be able to just call it like below or should I be wrapping this in 1 async function/wrap it in a Promise?
useEffect(() => {
loadMarkets();
loadBooks();
}, []);
async function loadMarkets() {
const marketInformation = await frService.getMarketInfo();
addMarketInfo(marketInformation.response.data);
}
async function loadBooks() {
....

loadMarkets();
loadBooks();
because these function are prefixed with the async keyword, these are promise. loadBooks will be fired before loadMarkets finishes.
simple answer, yes you can do as you wrote, however I would try to catch the errors with something like
loadMarkets().catch(doSomethingIfThereIsAnError)
where doSomethingIfThereIsAnError would be a function that does som...

It doesn't really matter which comes first since both of them are async. During the initial rendering of your component, useEffect will invoke both async functions. If you need to check which api endpoint gets called first and how much time it takes for the execution, you can open browser dev tools and check the network tab.

Related

async await not working as expected with react

I am calling an async function inside useEffect hook in react as below.
const ab = async () => {
console.log("start API");
await callAPI();
console.log("end API");
};
useEffect(() => {
ab();
console.log("calling");
}, []);
As the output first it will print start API then print calling and finally print end API. But what I need as the printing order is start API, end API, and calling. That's why I am using async await as well. But it's not working as expected. Any way to fix this issue?
That's the point of using await – the execution is paused until callAPI is finished.
To achieve the order you want, don't use await and just let the code run asynchronously. This way, the synchronous code (console.log('calling')) will be ran without waiting for the asynchronous code (callAPI()) to finish.
EDIT: However, depending on your use case, the other answer would probably make more sense.
For async/await to work , you'll have to await an asynchronous function.
Hence use the following code.
useEffect(() => {
let helper = async () => {
await ab(); // write await here
console.log('calling');
};
helper();
}, []);
Now the output would be:
Start API
End API
calling

What is the best way to execute a function after TWO or more async functions finish in React?

I have two functions that run asynchronously getting data from the API. Both of them are called from their own useEffect().
I have a third function that needs to run once those two functions have been fully completed.
How can this be accomplished?
Edit:
Both of the async functions look like this:
useEffect(() => {
fetchBudgetBucketsData();
}, [fiscalYear]);
useEffect(() => {
fetchBudgetBucketsData();
}, [fiscalYear]);
const fetchBudgetsData = async () => {
setIsFetchingBudgets(true);
const res = await getBudgets(orgID, `${parseInt(fiscalYear)}`, '', budgetType);
setIsFetchingBudgets(false);
if (isErrorResponse(res)) {
console.warn(res.details);
message.error(res.displayText);
return;
}
setBudgets(res.budgets);
};
const fetchBudgetBucketsData = async () => {
setIsLoadingBudgetBuckets(true);
if (orgID === undefined) {
return;
}
const res = await getBudgetBuckets(orgID, fiscalYear);
setIsLoadingBudgetBuckets(false);
if (isErrorResponse(res)) {
console.warn(res.details);
message.error(res.displayText);
return;
}
setBudgetBuckets(res.buckets);
};
Whenever the budget data or bucket data is updated, I want to call another function that checks for errors. However when the page loads, I need it to wait for both of those functions to be finished before it checks for errors.
Edit #2:
After some debugging, it looks like the issue might have to do with when React updates the state. Since I am trying to check for errors in data saved in the state.
One way could be chaining Promises.
Promise.all([ApiCall1, ApiCall2])
// At this point two promises above will be resolved
.then(() => ApiCall3)
Read more
I discovered the issue was caused by how React chooses when to update the state and not how I was calling these functions asynchronously.
I was able to call my Error check function by hooking it into the output of the data fetch calls. This makes sure that the error check only runs when either the budgets or buckets are edited and finished being changed.
useEffect(() => {
getWarningsAndErrors();
}, [budgets, budgetBuckets]) //Update errors whenever we edit budgets or buckets

Why doesn't useEffect directly support async callbacks or have separate parameters for the cleanup function?

I know I can't directly pass an async callback like this to useEffect
useEffect(async () => { // not supported, as this implicitly returns a Promise
const result = await axios(
'https://someurl',
);
setData(result.data);
});
as React expects nothing or a (cleanup) function callback as the first parameter for useEffect.
What I don't understand though: Is there any specific reason for this design choice? Why isn't there instead a signature like useEffect(callback, cleanup, dependencies) which would then allow me to directly pass in an async callback as first parameter, as the cleanup function could be easily passed in as second parameter?
What I don't understand though: Is there any specific reason for this
design choice?
One of the reasons that comes to mind is following. In react often when you return function from useEffect it does job like unsubscribing from things etc. and often you might need to access some variables from useEffect. For example:
useEffect(() => {
let cancelled = false;
fakeFetch(person).then(data => {
if (!cancelled) {
setData(data);
}
});
return () => {
cancelled = true;
}
}, [person])
With your design, you wouldn't be able to do above.

Understanding async dispatch actions using redux thunk

I was just going though the files that dispatches ACTIONS in a reactjs app and basically came across the following function::-
// When app inits
export const init = () => async dispatch => {
dispatch({ type: TYPES.SET_LOADING });
await dispatch(getConfig());
await dispatch(getGenres());
dispatch({ type: TYPES.REMOVE_LOADING });
};
I am a bit confused as to what the async is doing ahead of the dispatch , i am used to seeing normal vanilla javascript async functions like so:
anasyncfunc = async () => {
// write you're code here
}
But the above code confuses me a little. Can somebody please explain this to me.
A function which uses the await keyword must me marked with async which you have pointed out in your example
anasyncfunc = async () => {
// write you're code here
}
In this function we can now use await since it was marked with async.
In the case of the thunk, we are effectively creating an outer function called init which when called will return an anonymous function. This anonymous function will accept dispatch as an argument and will make use of the await keyword, and as such needs to be marked with the async keyword.
In short, we really are just creating a function which will want to use await and therefor must be marked with async.
I hope this clarifies it.

Why we use async before function in react

Sometimes we use async before the function. I want to know why and what is the proper use of async.
async remove(id) {
axios.delete('http://localhost:9022/users/delete/'+id)
.then(res => {
let updatedUsers = [...this.state.users].filter(i => i.id !== id);
this.setState({users: updatedUsers});
});
}
& what is the meaning of this
Users.propTypes = {
classes: PropTypes.object.isRequired,
};
An asynchronous function is a function which operates asynchronously
via the event loop, using an implicit Promise to return its result...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Async functions basically allow us to have nicer syntax for anything that does an asynchronous operation (API call, DB query, timeout, etc...).
We you define a function as async, you gain access to the await keyword, which prevents you from having to deal with callback functions or promise chaining.
For example:
async function foo() {
let example = await apiQuery();
...
}
If you didn't specify a function as async, you would have to do it this way.
function foo() {
apiQuery().then((data) => console.log(data));
...
}
You can see the first example provides a more clear approach to dealing with async functions. Working with multiple async function calls can start to get messy without it.
As for your second question.
PropTypes are a way of telling other developers that your React component requires some external input (props) to work correctly. So in your case, the Users component requires a prop titled classes that is of the type Object
See more here - https://reactjs.org/docs/typechecking-with-proptypes.html

Resources