Send Multiple Data With Axios - reactjs

I have a problem , my problem is when i send multiple data with axios , the image in formdata dosen't send , but when i send only the formdata it works , if any know how to send multiple data ins axios just give me what's the solution
const onSubmit = async (data) => {
if(loading) return ;
setLoading(true);
const formData = new FormData();
formData.append("image",image);
let details = {
name:data.name,
image:formData,
price:data.price,
description:convertToRaw(editorState.getCurrentContent()).blocks[0].text,
qty:data.qty,
promo:data.oldPrice,
categorie:data.categorie,
// images:[image,image2,image3,image4]
}
try{
let config = {
headers:{
authorization:"Authorization Token "+jwt,
"Accept": "application/json",
"Content-Type": "multipart/form-data",
}
}
await axios.post('../../api/products',details,config)
.then(res => console.log(res.data))
.then(setLoading(false))
.catch(err => console.log(err))
}catch(err){
console.log(err);
}
}

I would do something like this while uploading with images:
const onSubmit = async (data) => {
if(loading) return ;
setLoading(true);
const formData = new FormData();
formData.append("image",image);
let details = {
name:data.name,
price:data.price,
description:convertToRaw(editorState.getCurrentContent()).blocks[0].text,
qty:data.qty,
promo:data.oldPrice,
categorie:data.categorie
}
for (let key in details) {
formData.append(key, details[key]);
}
try{
let config = {
headers:{
authorization:"Authorization Token "+jwt,
"Content-Type": "multipart/form-data",
}
}
await axios.post('../../api/products',formData ,config)
.then(res => console.log(res.data))
.then(setLoading(false))
.catch(err => console.log(err))
}catch(err){
console.log(err);
}
}

Related

react useState() not updating state as expected

const [refreshBtnClicked, setRefreshBtnClicked] = React.useState(false);
const refreshClicked = () => {
setRefreshBtnClicked(true);
fetchAnalytics();
}
const fetchAnalytics = async () => {
setLoading(true);
try{
let analyticsResponse = await Axios({
method: 'post',
url: process.env.REACT_APP_BEATS_GENERAL_REPORT,
headers: {
"Access-Control-Allow-Origin": "*",
Authorization: "Bearer " + sessionStorage.getItem("idToken")
},
data: formData
})
setAnalyticsData(analyticsResponse.data);
setShowCards(true);
refreshBtnClicked && ToastSuccess('Updated successfully');
setRefreshBtnClicked(false);
setLoading(false);
}catch(err){
console.log(err);
ToastError('Error while fetching data');
setLoading(false);
}
}
i need to show the toast if refreshBtnClicked is true even though i set it to be true when the refresh button is clicked It still shows the state as false . But i am setting the state as false after the toast is displayed. can't understand y..
Because setState is asynchronous and you immediately invoke fetchAnalytics, so the new state is not yet available to it.
refreshBtnClicked doesn't need to be state at all; in fact you don't need the value at all since you can just await for the fetch to complete, and toast in the refresh clicked function.
const refreshClicked = async () => {
await fetchAnalytics();
ToastSuccess("Updated successfully");
};
const fetchAnalytics = async () => {
setLoading(true);
try {
let analyticsResponse = await Axios({
method: "post",
url: process.env.REACT_APP_BEATS_GENERAL_REPORT,
headers: {
"Access-Control-Allow-Origin": "*",
Authorization: "Bearer " + sessionStorage.getItem("idToken"),
},
data: formData,
});
setAnalyticsData(analyticsResponse.data);
setShowCards(true);
setLoading(false);
} catch (err) {
console.log(err);
ToastError("Error while fetching data");
setLoading(false);
}
};

dataLoaded state only changed after page reloaded

I'm doing an API call to get some data. then I keep a useState called dataLoaded. on a successful API call I make the dataLoaded=true. but to see it changed I have to reload the page.
following is my code.
const [dataLoaded, setDataLoaded] = useState(false)
useEffect(() =>{
const url = `${process.env.REACT_APP_DEV_BASE_URL}/v1/movie/`+ path.eventId + `/venue/`+ path.venue +`/showtime`;
const requestOptions = (token) => {
return ({
method: 'GET',
headers: { 'Content-Type': 'application/json', 'client_token': '4ece-9e89-1b6d4d2cbb61' }
})
};
const fetchData = async () => {
try {
const response = await fetch(url, requestOptions());
const json = await response.json();
// console.log(json);
// console.log(json.data.venueDateShowtime)
setShowTimes(json.data.dateShowtimes[0].showtimes[0]);
console.log(json.data.dateShowtimes[0].date)
setShowdate(json.data.dateShowtimes[0].date);
setDataLoaded(true);
console.log(dataLoaded)
console.log(showTimes.showtimeId)
console.log(showdate)
if(dataLoaded){
getSeatsArrangement();
}
console.log('jjjj')
}
catch (error) {
console.log("error",error);
}
};
fetchData();
},[]);
const getSeatsArrangement = async () => {
const requestOptions = (token) => {
return ({
method: 'GET',
headers: { 'Content-Type': 'application/json', 'client_token': '4ece-9e89-1b6d4d2cbb61' }
})
};
console.log(showTimes.showtimeId)
console.log(showdate)
try{
const url = `${process.env.REACT_APP_DEV_BASE_URL}/v1/seat?venueId=` + path.venue + `&movieId=`+ path.eventId +`&showtimeId=1011&movieDate=2022-10-11`;
const response = await fetch(url,requestOptions());
const json = await response.json();
console.log(json)
setReservedSeats(json.data.reservedSeats.reservedSeat)
setNonReservedSeats(json.data.reservedSeats.nonReservedSeats)
console.log(reservedSeats)
console.log(nonReservedSeats)
} catch(error) {
console.log("error",error);
}
}
Console logs when page loads
What is the aim of the code? fetchData is performed once after page loading (because of using ,[] at the end of useeffect.
And a remark: If you log your state right after setting it, the previous value will be shown! you should define another useeffect with your state as dependency (for each state) and log your state in there.
useEffect(() => {
console.log(dataLoaded)
if(dataLoaded){
getSeatsArrangement();
}
console.log('jjjj')
}, [dataLoaded]);
useEffect(() => {
console.log(showTimes.showtimeId)
}, [showTimes]);
useEffect(() => {
console.log(showdate)
}, [showdate]);
useEffect(() =>{
const url = `${process.env.REACT_APP_DEV_BASE_URL}/v1/movie/`+ path.eventId + `/venue/`+ path.venue +`/showtime`;
const requestOptions = (token) => {
return ({
method: 'GET',
headers: { 'Content-Type': 'application/json', 'client_token': '4ece-9e89-1b6d4d2cbb61' }
})
};
const fetchData = async () => {
try {
const response = await fetch(url, requestOptions());
const json = await response.json();
// console.log(json);
// console.log(json.data.venueDateShowtime)
setShowTimes(json.data.dateShowtimes[0].showtimes[0]);
console.log(json.data.dateShowtimes[0].date)
setShowdate(json.data.dateShowtimes[0].date);
setDataLoaded(true);
}
catch (error) {
console.log("error",error);
}
};
fetchData();
},[]);

Axios post request not setting Content-Type to multipart/form-data

Im trying to upload an image to cloudinary from react, i am unable to make a post request using axios . This is the code :
const onSubmit = async (data) => {
const { files } = document.querySelector('input[type="file"]');
console.log(data);
if (data.files !== undefined || data.files !== null || data.files !== "") {
setLoading(true);
const formData = new FormData();
formData.append("file", files[0]);
formData.append("upload_preset", cloudinary_preset);
const options = {
headers: { "Content-Type": "multipart/form-data" },
data: formData,
};
const res = await axios.post(
`https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`,
options
);
const img = await res.json();
const imgUrl = img.secure_url;
data.thumbnail = imgUrl;
console.log(data.thumbnail);
console.log(res);
setLoading(false);
} else {
data.thumbnail = "";
}
};
the response that i got on my browser console :
But when i use fetch , i am successfully uploaded my images . Here is the code :
const onSubmit = async (data) => {
const { files } = document.querySelector('input[type="file"]');
console.log(data);
if (data.files !== undefined || data.files !== null || data.files !== "") {
setLoading(true);
const formData = new FormData();
formData.append("file", files[0]);
formData.append("upload_preset", cloudinary_preset);
const options = {
method: "POST",
body: formData,
};
const res = await fetch(
`https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`,
options
);
const img = await res.json();
const imgUrl = img.secure_url;
data.thumbnail = imgUrl;
console.log(data.thumbnail);
console.log(res);
setLoading(false);
} else {
data.thumbnail = "";
}
};
the responses :
My guess that i conclude from the web console is on the headers part, when i use axios even tho i already change the headers to content-type:multipart/form-data , it still being sent as application/json. But then again im still learning to read the console log , if someone know what is really happening please share your opinion!
You are getting application/json type because you are passing JS object options to data part in your Axios post call.
Setting headers should be done in 3rd argument of .post method:
Here is modified code where options variable is removed:
const onSubmit = async (data) => {
const { files } = document.querySelector('input[type="file"]');
console.log(data);
if (data.files !== undefined || data.files !== null || data.files !== '') {
setLoading(true);
const formData = new FormData();
formData.append('file', files[0]);
formData.append('upload_preset', cloudinary_preset);
const res = await axios.post(
`https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`,
formData,
{
headers: { 'Content-Type': 'multipart/form-data' }
}
);
const img = await res.json();
const imgUrl = img.secure_url;
data.thumbnail = imgUrl;
console.log(data.thumbnail);
console.log(res);
setLoading(false);
} else {
data.thumbnail = '';
}
};
Axios docs https://axios-http.com/docs/api_intro:
axios.post(url[, data[, config]])
NOTE
I think that when you add FormData type of data to body, axios will se Content-Type to be multiplart/form-data implicitly.
Turns out that axios return a promise , hence i need to use then&catch to make it works, here is my working solution :
const onSubmit = async (data, e) => {
const { files } = document.querySelector('input[type="file"]');
console.log(data);
if (data.files !== undefined || data.files !== null || data.files !== "") {
setLoading(true);
const formData = new FormData();
formData.append("file", files[0]);
formData.append("upload_preset", cloudinary_preset);
await axios
.post(
`https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`,
formData
)
.then((result) => {
const img = result.data;
const imgUrl = img.secure_url;
data.thumbnail = imgUrl;
setLoading(false);
})
.catch((err) => console.log(err));
} else {
data.thumbnail = "";
}
try {
setLoading(true);
await authAxios
.post("/api/project/", data)
.then((res) => {
console.log(res.data);
})
.catch((e) => {
console.log(e);
});
setLoading(false);
reset();
} catch (err) {
console.log(err);
}
};
After the images is uploaded to cloudinary , i fetch it to the data which then is gonna be sent to my mongodb along with the text form data.

react native base64 image upload fail with status code 400

I want to upload my image as base 64 to the server, after user pick image it stores as base64 in state and then I call upload function but it give me this error: request failed with status code 400.
I need to first call an API and it takes user id and respond with an upload name id, then I call upload image API
here is my implementation:
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
base64: true
});
setImage(result)
};
const uploadImagetoServer = async (userId) => {
let uploadId;
try {
const response = await axios
.post('URL', {
"id": userId
});
console.log('id res', response.data);
uploadId = response.data;
} catch (error) {
console.log(error.message);
}
try {
const response = await axios
.post('ANOTHER_URL', {
headers: {
'Content-Type': 'application/json'
},
"fileName": uploadId,
"fileBase64String": image.base64,
"folderName": "Users",
"fileExtension": ".jpg"
});
console.log('upload res', response.data);
} catch (error) {
console.log(error.message);
}
}
const allowAccess = async () => {
if (Platform.OS !== 'web') {
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert('Sorry, we need camera roll permissions to make this work!');
} else {
pickImage()
.then(() => {
uploadImagetoServer(userData.id)
})
}
}
}
anyone can help me with this? ty
you need to add contentType in headers
'Content-Type': `multipart/form-data;`,
here is an example
npm install --save form-data
import FormData from 'form-data'
let data = new FormData();
data.append('file', file, file.name);
return (dispatch) => {
axios.post(URL, data, {
headers: {
'accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.8',
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
}
})
.then((response) => {
//handle success
}).catch((error) => {
//handle error
});
};}

How to post 2 APIs at a time while doing on submit method using reactjs?

I'm new to react, i'm doing a small project where i have created a form and i want to add file also. Form having one API and for uploading files having another api.
handleSubmit = e => {
e.preventDefault();
const { firstName, LastName, phoneNumber} = this.state;
const data = {
firstName,
lastName,
phoneNumber
};
axios.post(`/api/Form`, data, {
headers: { 'Content-Type': 'application/json' }
})
.then(res => {
console.log(res)
console.log(res.data);
})
.catch((err) => {
console.log(err)
})
for files:
uploadFile = (files) => {
var formData = new FormData();
files.map((file, index) => {
formData.append(`file${index}`, file);
});
fetch('/api/uploadFiles', {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(success => {
})
.catch(error => console.log(error)
);
}
I couldn't able to figure it out how to write both apis in submit method. Can anyone help me in this query? I'm not sure how to give 2 apis in submit method.
Assign your formData to State
uploadFile = (files) => {
var formData = new FormData();
files.map((file, index) => {
formData.append(`file${index}`, file);
});
this.setState({file:formData});
}
Then Post your 2 API's in handleSubmit
handleSubmit = e => {
e.preventDefault();
const { firstName, lastName, phoneNumber, file} = this.state;
const data = {
firstName,
lastName,
phoneNumber
};
axios.post(`/api/Form`, data, {
headers: { 'Content-Type': 'application/json' }
}).then(res => {
console.log(res)
console.log(res.data);
}).catch((err) => {
console.log(err)
});
if(file) {
fetch('/api/uploadFiles', {
method: 'POST',
body: file,
}).then(response => response.json()).catch(error => console.log(error));
}
}

Resources