Understanding async dispatch actions using redux thunk - reactjs

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.

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

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.

How does a react action have access to dispatch?

In my react project I have an actions file that looks like this:
const startLoad = () => async (dispatch) => {
dispatch({
type: CONTENT_LOAD,
});
};
// Get all content
export const getContents = () => async (dispatch) => {
dispatch(startLoad());
// some more code...
};
So in this example, I know that dispatch is coming from the middleware and getContents has access to it because it was mapped using mapDispatchToProps. So I am assuming when getContents is called, its really called like this -> dispatch(getContents) but can this be replicated in plain JavaScript so I can see what is really going on? If I am wrong about why getContents has access to dispatch please let me know.
For example, how isstartLoad able to use dispatch just because dispatch called startLoad? I have noticed that it will also work if I call it like this: dispatch(startLoad(dispatch));.
Passing dispatch in to startLoad actually makes more sense to me so I don't get why that isn't required.
Edit: this is the closest example I could come up with on my own.
const fun = () => (fun2) => {
fun2();
}
const fun2 = () => {
console.log('hello');
}
fun()(fun2);
So I am assuming when getContents is called, its really called like
this -> dispatch(getContents) but can this be replicated in plain
JavaScript so I can see what is really going on? If I am wrong about
why getContents has access to dispatch please let me know.
redux-thunk has quite simple implementation
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => (next) => (action) => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
As you can see it checks if action is a function.
And bonus, if you like you can get the whole state and extra argument in params following dispatch
For example, how isstartLoad able to use dispatch just because
dispatch called startLoad? I have noticed that it will also work if I
call it like this: dispatch(startLoad(dispatch));.
It looks like middleware also handles above case.

Purpose of Redux Thunk `([arg(s)]) => dispatch =>`?

The code below comes from a Udemy course on the MERN stack by Brad Traversy. I'm new to Redux and Redux Thunk and am trying to understand what the purpose of => dispatch => is. I know it comes from Redux Thunk, which was set up in the Redux store file. I think dispatch is being used here in order to dispatch more than one action from this function and read that the = ([arg(s)]) => dispatch => syntax is an example of currying (though that doesn't seem right since with currying each function has one argument).
I'd greatly appreciate any help understanding => dispatch =>.
(Other minor point of confusion: In the course the function setAlert is referred to as an action, but I'm not sure that's correct since it contains multiple dispatches of actions.)
export const setAlert = (msg, alertType, timeout = 5000) => dispatch => {
const id = uuidv4();
dispatch({
type: SET_ALERT,
payload: { msg, alertType, id }
});
setTimeout(() => dispatch({ type: REMOVE_ALERT, payload: id }), timeout);
};
There's a couple of things going on here:
1) setAlert is what is usually called an "action creator". It's a function that returns an action that you can dispatch later.
2) Redux-Thunk is allowing you to use functions of the form (dispatch) => {} as actions (in place of the more normal object form { type, payload })
It might help if you look at them individually before seeing how they combine together:
// This is an action creator (a function that returns an action)
// This doesn't use redux thunk, the action is just a simple object.
// Because it's an action creator you can pass in arguments
// Because it's not a thunk you can't control when then dispatch happens
const setAlertActionCreator = (msg, alertType) => {
const id = uuidv4();
return {
type: SET_ALERT,
payload: { msg, alertType, id }
};
};
// You use this as:
dispatch(setAlertActionCreator("msg", "type"));
// This is not an action creator it's just an action.
// This IS a redux-thunk action (it's a (dispatch) => {} function not a simple object)
// Because it's not an action creator you can't pass in arguments to get a custom action back
// Because it IS a redux-thunk action you can dispatch more actions later
const setAlertThunk = (dispatch) => {
setTimeout(() => dispatch({
type: SET_ALERT,
payload: {
message: "fixed message",
alertType: "fixed alertType",
id: "fixed id",
}
}), 5000);
};
// You use this as:
dispatch(setAlertThunk);
// When you combine both patterns you gain the ability
// to both pass in arguments and to create additional dispatches
// as the function runs (in this case dispatching again after a timeout.)
// I won't repeat your code, but will show how you would call it:
dispatch(setAlertActionCreator("msg", "type"));
// ie: you use it the same way as example 1.
The syntax () => dispatch => is equivalent to:
function response(){
return function (dispatch){
//Some code here
}
}
So, basically what you can say is, it is a modern way of writing the same function. => dispatch => is returning a function that will be executed when the action will be invoked.
Hope this will help.
=> dispatch =>
is nothing but a syntactical sugar over a function returning another function. Since Fat-arrow functions => are used in place of normal functions.
Like
function abc(a,b){
return a+b;
}
is same as const abc = (a,b) => a+b ;
So you dont have to write return keyword.
So in your case its the same => dispatch => and the one below , its returning an anonymous function with . dispatch as its arguement
function response(){
return (dispatch){
//some code here
}
}
Hope it helps, feel free for doubts

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