Upload Multiple Image in React using axios - reactjs

I have here a problem with multiple images. My problem is that I want to upload multiples image through an API. The API can't handle it through one request. That's why I wanted to upload images one by one and call the API one by one. How do i do it?
export const saveImages =
({ images = [], oldImages, isNew }) =>
async (dispatch) => {
try {
dispatch({
type: constants.REQUEST,
});
let responses;
if (images?.length) {
let formData = new FormData();
const requests = images.map(({ imageFileName, imageFile }) => {
formData.append(imageFileName, imageFile);
formData.append("isNewProduct", isNew);
return axios.post(
`${URL}/saveImages`,
formData
);
});
responses = await Promise.all(requests);
}
dispatch({
type: constants.SUCCESS,
payload: [...(oldImages || []), ...response?.data],
});
} catch (error) {
dispatch({
type: constants.FAILURE,
});
}
};

If you really need to split them up into individual requests then map the images to an array of Promises (axios.post) and await Promise.all(....) them. When all mapped promises resolve then Promise.all resolves.
export const uploadMultipleImages = ({ images }) => async (dispatch) => {
try {
dispatch({ type: constants.REQUEST });
// Map images to array of axios.post Promises
const requests = images.map(({ imageFileName, imageFile })=> {
const formData = new FormData();
formData.append(imageFileName, imageFile);
return axios.post(`${URL}/upload-image`, formData);
});
// await all promises to resolve, responses is an array of all
// resolved Promise values, i.e. whatever the POST requests
// return
const responses = await Promise.all(requests);
dispatch({
type: constants.SUCCESS,
payload: responses,
});
} catch (error) {
dispatch({ type: constants.FAILURE });
}
};
If I recall correctly on previous questions sometimes the images would have missing properties, so if this is still the case then you may want to use a .filter function before mapping to POST requests.

Related

React native data are getting in formvalues but while .post it got failed

In console of formvalues values are coming but while sending its not getting in response of console..its become status : 400 and field is required showing but same piece of code is done in expo nd working fine but in react native cli its not working please let me know how can i solve this issue...
export const login = (formValues, actions) => {
return async dispatch => {
dispatch(startSubmitting());
const url = `/auth/login`;
const formdata = new FormData();
formdata.append('email', formValues.email);
formdata.append('password', formValues.password);
console.log(formValues,'formValues');
const response = await api
.post(url, formdata)
.then(res => {
console.log(res,'res');
return res;
})
.catch(error => {
actions.setErrors(error.response.data.error);
console.log(error.response.data.error);
return error.response;
});
dispatch({
type: 'LOGIN',
payload: response,
});
dispatch(stopSubmitting());
if (response && response.data && response.data.access_token) {
await AsyncStorage.setItem('userToken', response.data.access_token,2);
}
};
};

Axios get in stock items

I am trying to filter products whether it is available or not.
Not sure how to pass an axios request with ">" logic.
I've started to create an Action
export const listProductAvailable = () => async (dispatch) => {
dispatch({
type: PRODUCT_AVAILABLE_LIST_REQUEST,
});
try {
const { data } = await Axios.get(`/api/products?countInStock>0`);
dispatch({ type: PRODUCT_AVAILABLE_LIST_SUCCESS, payload: data });
} catch (error) {
dispatch({ type: PRODUCT_AVAILABLE_LIST_FAIL, payload: error.message });
}
};
But I don't think that such a request is possible.
const { data } = await Axios.get(/api/products?countInStock>0);
Also, I don't see myself changing my Product Model creating an isAvailable boolean field as it would be redundant with countInStock =0 or not.

Fetch array of url's

I'm working with redux and I am trying to fetch Star War API.
Here is my code:
import { MOVIES_ERROR, MOVIE_CHARACTERS } from "./types";
// Get all characters
export const getCharacters = (userId) => async (dispatch) => {
try {
const res = await fetch(`https://swapi.dev/api/films/${userId}`);
if (!res.ok) {
throw new Error("sometheing went wrong");
}
const getData = await res.json();
const characters = await getData.characters;
let people = [];
Promise.all(
characters.map((url) =>
fetch(url)
.then((response) => response.json())
.then((name) => people.push(name))
)
);
dispatch({
type: MOVIE_CHARACTERS,
payload: people,
});
} catch (err) {
dispatch({
type: MOVIES_ERROR,
payload: { msg: err.response.statusText, status: err.response.status },
});
}
};
when I make a console log inside a promise. all I got people array filled with all the data, but when I dispatch it I got an empty array in the reducer. can anyone tell me what the mistake that i did?
I got the problem just now, I need to add await before Promise.all :)

Map over Axios Response and append 2nd Axios Response to 1st

I'm creating a movie search React App using axios and the TMDb API. I want to make an axios.get call to search for a movie based on query, then map over the response, and pass the movie.id for each movie into a 2nd axios call to get more details for each movie.
I have tried many approaches, but I'm confused about how I need to return the values, or if I need to use async/await at some point in the code to wait for responses. I don't really know the best way to go about this - there's got to be a simple way to do it in sequence, but the asynchronous nature of the problem makes this difficult for me.
I thought it would be simpler to make my first axios call inside my search function, and then write a second function getDetails(id) that takes a movie id and makes an axios call with it.
Ideally, if I call the getDetails function in a map, get a response, append that response to my movies array, I could easily have an array of movies with appended details to each individual movie. I could then store the entire array in state, and use a single piece of state to manage all my movie data. I know that this process is not synchronous and that axios is promise based, but is there a way to go about this sequentially or am I approaching it all wrong? I know that .push() is not working in this situation, but I have tried other methods and they have always returned undefined, a promise, or an unintended result.
const search = query => {
axios
.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
)
.then(response => {
response.data.results.map(movie => {
const details = getDetails(movie.id);
return movie.push(details);
});
});
};
const getDetails = id => {
axios
.get(
`https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
)
.then(response => {
return response.data;
});
};
EDIT 1: I've played with the answer by Abanoub Istfanous, and it seemed to return undefined with the added dispatch to update my state. I tweaked it more and the second set of code marked WORKING seems to be displaying some search results, but I cannot render any of the appended data from getDetails to the screen, as they are showing undefined. Am I still doing something incorrectly?
NOT WORKING:
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: data
});
return data;
};
// getDetails is unchanged...
WORKING:
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: response.data.results
});
return data;
};
// getDetails is unchanged...
I recommend to use Promise
/*
*#return data
*/
const getDetails = async (id) => {
const response = await axios
.get(
`https://api.themoviedb.org/3/movie/${id}?api_key=${API_KEY}&language=en-US`
)
return response.data
};
then
const search = async (query) => {
const response = await axios
.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = Promise.all(response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
}))
return data
};
The reason why it returns undefined is because Promise.all() will be executed asynchronously on the job queue and will only return the result after all Javascript gets executed and the call stack gets empty. So a simple solution to your code will be placing an await before Promise.all().
const search = async query => {
dispatch({
type: MOVIE_SEARCH_REQUEST
});
const response = await axios.get(
`https://api.themoviedb.org/3/search/movie?api_key=${API_KEY}&language=en-US&query=${query}&page=1&include_adult=false`
);
const data = await Promise.all(
response.data.results.map(async movie => {
movie.details = await getDetails(movie.id);
})
);
dispatch({
type: MOVIE_SEARCH_COMPLETE,
payload: response.data.results
});
return data; //No need to return data since you are dispatching it to redux store
};
You can read more about the asynchronous nature of JS on browsers here:
https://medium.com/#Rahulx1/understanding-event-loop-call-stack-event-job-queue-in-javascript-63dcd2c71ecd

Creating Components based on multiple axios requests

I'm working on redux-thunk project which i need to reach out endpoint-1 to get which & how many components i need to show in a page. Then i'm required to use this return to reach out endpoint-2 and get the data with the parameters from the enpoint-1.
I'm having hard time to create the correct logic. Also i'm sharing a diagram which i hope gives you the idea and requirements.
Flow Diagram
Thanks
export const fetchByPage = () => async dispatch => {
const response = await streams.get("byPage?", {
params: parameters.byPageParams
});
console.log(response.data);
dispatch({ type: FETCH_BY_PAGE, payload: response.data });
};
export const fetchPersons = () => async dispatch => {
const response = await streams.get(URL, {
params: parameters.byCriteriaParams
});
dispatch({ type: FETCH_PERSONS, payload: response.data });
};
Here are my actions. I'm trying to update byCriteriaParams with the data returns from fetchByPage call.

Resources