Why we use async before function in react - reactjs

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

Related

Custom hook returning a promis

Is it possible to return a promise from a custom react hook and await for it? Like:
const getData = useMyCustomGetDataHook();
const fetchData = async () => {
await getData({...props});
// ... do stuff..
}
In reality, there is no such thing as a custom React Hook - it is simply a fancy name for a function having a name that starts with use. Thus, any function can be a custom React Hook - including a function that returns a Promise that you can await.
However the real problem is that your async function won't be usable inside a component. render() is not async and you cannot await. In fact a custom React Hook is more about the programming paradigm that the function itself.
What you need to do in your case is to launch your async operation either from useEffect() - if it does not require that DOM is created, or from useLayoutEffect() - if it requires it - and then trigger a state change in the .then() handler. This is the React way of doing this.
You can't directly await for a promise while rendering (aside from the experimental suspense stuff).
You could use e.g. useSWR() as a wrapper for a promise-returning function (which, wink wink, could be e.g. something that uses fetch()...).
async function getData(x) {
return x * 4;
}
function useData(x) {
return useSWR(['myData', x], (_, x) => getData(x));
}
function MyComponent() {
const dataSWR = useData(8);
if(dataSWR.data === undefined) {
return <>Loading...</>;
}
return <>{dataSWR.data}</>;
}

Call multiple async functions using useEffect

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.

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.

what's the difference between these two callback in react-redux?

I am learning react-redux with the Udemy course. Meet this code,
export function createPost(value, callback){
const request = axios.post(url, value).then(() => callback());
}
why not just put the callback like this
const request = axios.post(url, value).then(callback);
EDIT
in the video they call this function like this
this.props.createPost(value, () => this.props.history.push('/'));
2.
Since they called by this.props.createPost(value, () => this.props.history.push('/'));
I thought the callback is already a function () => this.props.history.push('/') ;
so why they wraped the callback again in the definition createPost by Promise.then(() => callback())
In my opinion just put the callback like Promise.then(callback) is ok.
Am I wrong?
if you take a closer look your function call takes one param, which means if you append parenthesis at the end it will be IMMEDIATELY called:
this.props.history.push('/')
if you try to do:
this.props.createPost(value, this.props.history.push('/')); // without the () =>
the function history.push will be called immediately, what you are doing is context binding, by creating a lambda function you are delaying the execution and also adding a constant param '/'.
Another way to achieve this:
this.props.createPost(value, this.props.history.push.bind(null, '/')
Read Bind
If your function did not take any params then you could do as you wish (without the parenthesis ofc)
this.props.createPost(value, this.props.anotherFunction) // anotherFunction does not take any params, and does can be passed as is

Resources