Sequential Call of API in React and Redux - reactjs

I need to upload multiple images but I also need to upload them one by one.
I wanted to upload them sequentially. First, you need to wait for the previous API response before calling another API response. How will I do it?
Currently is that I'm calling them in parallel. Whoever upload image API response has finished first, will be displayed.
export const uploadPhotos =
({ photos, size, controller }) =>
async (dispatch) => {
await Promise.all(
photos.forEach(async (photo, index) => {
const formData = new FormData();
formData.append("photo", photo);
dispatch({ type: constants.UPLOAD_PHOTOS_START, size });
try {
const response = await axios.post(
`${API_URL}/photos/upload`,
formData,
{
onUploadProgress({ loaded, total }) {
dispatch(setUploadProgress({ id: index, loaded, total }));
},
signal: controller.signal,
}
);
dispatch({
type: constants.UPLOAD_PHOTOS_SUCCESS,
payload: response.data,
});
} catch (error) {
dispatch({
type: constants.UPLOAD_PHOTOS_FAILURE,
payload: error,
});
}
})
);
};
export const setUploadProgress = (progress) => ({
type: constants.SET_UPLOAD_PROGRESS,
payload: progress,
});
export const resetUploadData = () => ({
type: constants.RESET_UPLOAD_DATA,
});
export const setOverallSize = (data) => ({
type: constants.SET_OVERALL_SIZE,
payload: data,
});

First: await Promise.all(photos.forEach(async () => {})) will have no effect.
forEach does not return a value so you want .map instead.
But for sequential calls, something like this is preferred:
export const uploadPhotos =
({ photos, size, controller }) =>
async (dispatch) => {
for (const [index, photos] of photos.entries()) {
const formData = new FormData();
formData.append("photo", photo);
dispatch({ type: constants.UPLOAD_PHOTOS_START, size });
try {
const response = await axios.post(
`${API_URL}/photos/upload`,
formData,
{
onUploadProgress({ loaded, total }) {
dispatch(setUploadProgress({ id: index, loaded, total }));
},
signal: controller.signal,
}
);
dispatch({
type: constants.UPLOAD_PHOTOS_SUCCESS,
payload: response.data,
});
} catch (error) {
dispatch({
type: constants.UPLOAD_PHOTOS_FAILURE,
payload: error,
});
}
}
};

Related

after logging in my 2nd action is not getting dispatch after login success action

This is my auth.js action file where i have created loginUser and loadUser action. Inside loginUser action i have called loadUser() action. But the action loadUser is not being activated after LOGIN_SUCCESS action type.
export const loadUser = () => async (dispatch) => {
if (localStorage.token) {
setAuthToken(localStorage.token);
}
try {
const res = await axios.get('/api/auth');
dispatch({
type: USER_LOADED,
payload: res.data,
});
} catch (err) {
dispatch({
type: AUTH_ERROR,
});
}
};
export const loginUser = (email, password) => async (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const body = JSON.stringify({
email,
password,
});
try {
const res = await axios.post('/api/auth', body, config);
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
dispatch(loadUser())
} catch (err) {
const error = err.response.data.msg;
if (error) {
dispatch(setAlert(error, 'danger'));
}
dispatch({
type: LOGIN_FAILED,
});
}
};
i tried so much to figure out the error but i dont know what is interfering with the action due to that only the first action is activated. Please help me. Thanks.
If you're just going to use it for the second action, then you don't need to export loadUser() method.
Just have it be a method in that file and then call it after the dispatch
...
dispatch({
type: LOGIN_SUCCESS,
payload: res.data,
});
loadUser();
...

How to change this promise returned function into an async await?

Initially I write my code with promise based script .then().catch
But when I tried to change it into the async await function. Its not working anymore.
Please someone help me with this.
My Old Code Which is working
export const fetchToken = (params) => {
return (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
return axios
.post(`/api/token`, params, config)
.then((res) => {
tokenData = res.data.access_token;
dispatch({
type: LOGGED_IN,
payload: res.data,
});
})
.catch((err) => {
console.log(err);
alert('Provided username and password is incorrect');
throw err;
});
};
};
As you can see in the above code the function is returning a promise. But When I try to change it into async await
My simulator is give me Unexpected reserved work await Error
Here is my async await code in redux
export const fetchToken = async (params) => {
return (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
try {
const response = await axios.post(`/api/token`, params, config);
const data = await response.json();
tokenData = data.access_token
dispatch({ type: LOGGED_IN, payload: res.data})
} catch {
console.log(err);
alert('Provided username and password is incorrect');
}
};
};
Your async is applied to the wrong function, it should be on the dispatch function
export const fetchToken = (params) => (
async (dispatch) => {
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
};
try {
const response = await axios.post(`/api/token`, params, config);
const data = await response.json();
tokenData = data.access_token
dispatch({ type: LOGGED_IN, payload: res.data})
} catch {
console.log(err);
alert('Provided username and password is incorrect');
}
};
);
NB: I've removed the braces; arrow function return is implied https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Fetching data using API in react.js

I am trying to fetch data using API in react.js. My code is like below
import Axios from 'axios';
export const getCountry = () => dispatch => {
return Axios.get('http://treeoverflow.com/api/country/listing/true/111111111111222222222222333333333333444444444444', { crossdomain: true })
.then(response => {
console.log(response.data);
var countryData = response.data;
dispatch({
type: 'getCountries',
payload: countryData
});
})
.catch(function(error) {
console.log('hello');
dispatch({
type: 'getCountryError',
payload: error
});
});
};
export default { getCountry };
I getting below view in Network tab.
But I am not getting result. Is there any issue in this URL 'http://treeoverflow.com/api/country/listing/true/111111111111222222222222333333333333444444444444' ?

Reducer not called after action return?

Here's my login action code. What am I doing wrong ? As you can see, reducer state update not called.
Please, help me guys!
React - 16.8
Axios Http Client
Node & Mongo Db Backend
export const loginUser = (userData) => {
axios.post(URL + '/api/admin/login', userData)
.then(res => {
return {
type: SIGNIN_USER,
payload: storeData
}
})
.catch(err => {
return {
type: SHOW_MESSAGE,
payload: err.response.data
}
});
};
.then(res => {
return {
type: SIGNIN_USER,
payload: storeData
}
})
Instead of returning res, apply an action to it here. You mentioned changing the state, so something similar:
.then(res => {
this.state.someResult = res;
})
You need to dispatch the action, not just return the object:
const dispatch = useDispatch(); // Assuming you're inside functional component
export const loginUser = (userData) => {
axios.post(URL + '/api/admin/login', userData)
.then(res => {
return dispatch({
type: SIGNIN_USER,
payload: storeData
})
})
.catch(err => {
return dispatch({
type: SHOW_MESSAGE,
payload: err.response.data
})
});
};
Try with this code sample :
export const loginUser = userData => dispatch => (
axios.post(URL + '/api/admin/login', userData)
.then(res => dispatch({ type: SIGNIN_USER, payload: res }))
.catch(err => dispatch({ type: SHOW_MESSAGE, payload: err.response.data }))
)
Make use of Arrow functions it improves the readability of code. No need to return anything in API.fetchComments, Api call is asynchronous when the request is completed then will get the response, there you have to just dispatch type and data.
Below code does the same job by making use of Arrow functions.
export const bindComments = postId => {
return dispatch => {
API.fetchComments(postId).then(comments => {
dispatch({
type: BIND_COMMENTS,
comments,
postId
});
});
};
};
reference link : React-Redux: Actions must be plain objects. Use custom middleware for async actions

reactjs importing imported JSON object into array-list

I can display a JSON object that I get with redux.
but when returning, the list is empty.
How do I transfer a JSON object that I send into list as
payload:
return {
type: USER_INFO,
payload: {
profile: list
},
}
export const USER_INFO = 'USER_INFO';
let list = [];
export function userAction(newValue) {
fetch("http://127.0.0.1:8000/api/account/me", {
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
}
})
.then((response) => response.json() )
.then((responseData) =>{
list = JSON.stringify(responseData);
console.log(list);
// console.log(JSON.parse(liste));
return list;
});
**//list appears empty when I check here**
**console.log(list);**
return {
type: USER_INFO,
payload: {
profile: list
},
}
}
How I handle asynchronous requests with Redux.
I'll have actions for each type of status the user info action could have. For example, there's three states of the user info request: default, loaded, and failed.
const userInfoRequest = () => { type: USER_INFO_REQUEST };
const userInfoLoaded = (userInfo) => { type: USER_INFO_LOADED, userInfo };
const userInfoFailed = (error) => { type: USER_INFO_FAILED, error };
You're going to need to turn the userInfo action into a thunk so that the action can property handle its internal asynchronous state inside the action creator.
const userInfoRequest = () => (dispatch, getState) => {
dispatch(userInfoRequest());
fetch(...)
.then(response => response.json())
.then(result => dispatch(userInfoLoaded(result))
.catch(error => dispatch(userInfoError(error))
}

Resources