send file and data to server with Axios - javascript

I am using ReactJs and wanna send data to Laravel API with Axios.
I try
export const send = (data, File) => {
const formData = new FormData();
formData.append('media', File);
try {
PostRequest.post('/post', { formData, data })
.then(r => console.log(r.data))
.catch(e => console.log(e));
} catch (error) {
console.log(error);
}
};
and I call send like this :
let data = {
mobile: mobile,
email: emailAddress,
userName: userName,
password: password,
firstName: firstName,
lastName: lastName,
website: website,
bio: bio,
date: selectedDay,
code: code,
};
console.log(profile);
console.log(data);
send(data, profile);
the log
but form data is null in the response
I set the header like this :
headers: {
"Content-Type": "multipart/form-data",
"Accept":"application/json"
}
also I try
const formData = new FormData();
formData.append('media', profile);
let data = {
mobile: mobile,
email: emailAddress,
userName: userName,
password: password,
firstName: firstName,
lastName: lastName,
website: website,
bio: bio,
date: selectedDay,
code: code,
media: formData,
};
send(data);
but the media is null

The problem is not with your implementation at all. You can't log the formData in the console and expect to see its entities as the other objects.
So, the empty formData on the console is proper behavior. if you really want to inspect your formData, take a look at this post.
thus, your send method is working properly and sending the correct data to the server.
Optional
On the server, you need to get the formData and parse it, so it must be implemented on the server-side. since you need to get the body request in formData, you could append all your data in the whitin a formData and send a single formData, but its depened on the backend implementation, if you can change the server-side, I engourage you to appnend all your data in the formData and then send it.

you can have an uploader like this , which will work with ;)
const Uploader = ({ url, updateData }) => {
function handleUpload(e) {
if (e.target.files[0]) {
console.log(e.target.files);
const formData = new FormData();
formData.append("config", e.target.files[0], e.target.files[0].name);
console.log(formData);
axios.post(url, formData).then(res => {
updateData(res);
});
}
}
return (
<label>
<div className={styles.uploaderBtn}>
<input
type="file"
style={{ display: "none" }}
onChange={e => {
handleUpload(e);
}}></input>
<img src={Upload} alt="" />
</div>
</label>
);
};

Related

State not updating within a promised fetch (react)

I have a form with which i am sending data to my api. The data is used to create backend admin accounts and also create post entries. I need to post the data in a certain order to get some dynamic fields from the admin account to the post. For example:
create the admin account to make an id field
use the id field and apply to the post to create a unique link between admin account and post
Everything works apart from one state update that i'm trying to do after fetching the freshly created account:
// dont know what the ID will be as its dynamic
const [theID, setTheID] = useState('');
//Send the data to firstly create the admin account (works fine)
fetch('example.com/api/cockpit/saveUser', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY
},
body: JSON.stringify({
user: {
user: firstname.toLowerCase()+surname.toLowerCase(),
name: firstname,
email: email,
password: password,
group: 'consumers',
}
})
})
.then(user => user.json())
// make next fetch a chain of the promise
// fetch all accounts but filter by email so will only return the right one
.then(()=>{
return fetch(`example.com/api/cockpit/listUsers&filter[email]=${email}`,{
method: 'post',
headers: {
'Content-Type': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY
}
})
})
.then((res) => {
return res.json();
})
.then((res)=>{
// the console log works fine
console.log(res[0]._id);
// the state returns undefined
setTheID(res[0]._id);
})
.catch((err)=>{
console.error(err);
})
//Then last fetch to make the post entry works fine ...
.then(()=>{
return fetch('example.com/api/collections/save/consumers', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY,
},
body: JSON.stringify({
data: {
firstname: firstname,
surname: surname,
password: password,
email: email,
project_name: projectName,
project_template: tmp,
// expected to get the dynamic ID front the state
ass_consumer: theID,
slug: projectName.toLowerCase().replace(' ','') + '-rr',
username: firstname.toLowerCase()+surname.toLowerCase()
}
})
})
})
.then(user => user.json())
.then((user)=>{
setnewPage(user._id);
})
I've checked the console which shows up fine after fetching. All my other state changes are bound to the form inputs but i've never had this problem with updating state in a fetch before.
I've also tried creating a function that takes the email as an argument then returns the state change but no luck with that either.
Appreciate any help!
(using cockpit as my api)
EDIT
This is what the console log returns:
(i just need the _id)
{
user: "johndoe",
name: "john",
email: "john.doe#example.com",
active: true,
group: "consumers", 
_created: 1627039008,
_id: "60faa5203365618a38000035",
_modified: 1627039008,
}
You are most likely reading the state within the same operation ("too quickly"), so the state changes will not be reflected yet because the process to update React state is asynchronous.
You have 2 options to always get the most up to date state value:
Either use a reference to the state (check out this package)
Or use an "ugly" work-around taking the value from setState like this:
const [id, setId] = useState("")
setId("test")
console.log(id) // ""
// do this to get the up to date value, as the value
// in setState is always the most up to date one
let idVal
setId(current => {
idVal = current
return current
})
console.log(idVal) // "test"
So in your specific example, try this:
//Then last fetch to make the post entry works fine ...
.then(()=>{
let customerID
setTheID(current => {
customerID = current
return current
})
return fetch('example.com/api/collections/save/consumers', {
method: 'post',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Cockpit-Token': process.env.REACT_APP_API_KEY,
},
body: JSON.stringify({
data: {
[...]
// use the customerID variable, not the state variable
ass_consumer: customerID,
[...]
}
})
})
})

React Router Adds URL Query Params on POST Request

Hello my fellow nerds,
I am running into an issue where when I make a POST request (using Axios library inside of React function), it automatically appends all of the data from the "Create a User" form into search parameters in the URL of the page upon submission. I don't like this because I'd rather this stay hidden within the POST request, not flung out onto the page URL.
Image: URL after user was created
This is a direct result of React Router adding the data sent in the request of the body being appended to the location.search of react router's history object. So, naturally, since the react router history object is mutable, I tried adding this to the response of the submission:
this.props.location.search.replace({*some random parameter stuff here*});
This was in hopes it would remove all of that stuff from the URL and redirect to the page without search parameters. Anyways, I have seen a few other posts similar in nature but they don't seem to answer this exact question.
TL;DR: I am trying to send a POST request without React Router adding my req.body data to the params in my URL and the location.search object.
MY CODE:
Users.js: (front end)
handleSubmit (e) {
Axios.post(`${server}/s/admin/users/create`, {
headers: {
'Content-Type': 'application/json'
},
data: {
firstName: this.state.firstName,
lastName: this.state.lastName,
username: this.state.username,
password: this.state.password,
email: this.state.email
}
}).then((res) => {
console.log(res);
}).catch(err => console.log(err));
}
users.js: (back end)
app.post("/s/admin/users/create", (req, res) => {
let rb = req.body.data;
let newUser = new User({
_id: uid.time(),
orgID: req.session.orgID,
email: rb.email,
username: rb.username,
password: bcrypt.hashSync(rb.password, hashRate),
firstName: rb.firstName,
lastName: rb.lastName,
data: { exist: "true" },
settings: { exist: "true" }
});
// Save new owner to db
newUser.save((err, data) => {
if (err) return console.error(err);
res.json({info: `A new user, ${newUser.firstName} ${newUser.lastName}, has been created successfully.`});
});
});
Thank you!
P.S. This is my first post, thank you for your patience. I've tried searching and solving this issue for about a day now.
Can you try rewriting it this way? cause axios.post expect
axios({
method: 'post',
url: `${server}/s/admin/users/create`,
headers: {
'Content-Type': 'application/json'
},
data: {
firstName: this.state.firstName,
lastName: this.state.lastName,
username: this.state.username,
password: this.state.password,
email: this.state.email
}
}).then((res) => {
console.log(res);
}).catch(err => console.log(err));
Axios.post method expect the second argument as data but you have passed config, another way is to pass data and config in the third argument.
handleSubmit(e) {
Axios.post(`${server}/s/admin/users/create`, {
firstName: this.state.firstName,
lastName: this.state.lastName,
username: this.state.username,
password: this.state.password,
email: this.state.email
}, {
headers: {
'Content-Type': 'application/json'
}
}
}).then((res) => {
console.log(res);
}).catch(err => console.log(err));
}

Axios request not receiving formData with content-type set

I have the following data being added to my formData()
let uploadData = new FormData();
uploadData.append("peer-video", this.state.peerVideo);
uploadData.append("peer-video-thumbnail", this.state.peerVideoThumbnail);
uploadData.append("project-video", this.state.projectVideo);
uploadData.append(
"project-video-thumbnail",
this.state.projectVideoThumbnail
);
this.state.documents.forEach(item => {
uploadData.append("documents", item);
});
The uploadData has key value pairs in it, I did formData.entries() to check this. And my axios request is as follows:
export const addProject = data => dispatch => {
axios
.post("/api/portfolio/add-project", data, {
headers: {
"Content-Type": `multipart/form-data`
}
})
.then(res => {
dispatch({
type: ADD_PROJECT,
payload: res.data
});
})
.catch(err => {
dispatch({
type: ADD_PROJECT,
payload: err
});
});
};
And if I go to my payload in the network tab I see this:
{"uploadData":{}}
Any suggestions? Thank you for taking the time to help me.
Edit
I tried the following structure in my axios request and it yielded the same result.
axios({
method: "post",
url: "/api/portfolio/add-project",
data: data,
config: { headers: { "Content-Type": "multipart/form-data" } }
})
When I execute the following
for (let keys of uploadData.entries()) {
console.log(keys);
}
These are the values:
I also noticed on formData docs that
Note: If you specify a Blob as the data to append to the FormData object, the filename that will be reported to the server in the "Content-Disposition" header used to vary from browser to browser.
But i'm not sure if that's what is causing my issue here?
Welp, this is what happens when your eyes stare at a screen too long.
this.props.addProject({
title: this.state.title,
company: this.state.company,
description: this.state.description,
role: this.state.role,
skills: this.state.skills,
uploadData: uploadData
});
Needed to simply be:
this.props.addProject(uploadData)
Thank you #vortex
Looks like you are posting an undefined variable called data rather than your uploadData

How to extract localstorage values in reactjs

I am using form in reactjs. I stored user data in localstorage now I want to upload file and i want to store file key with userID which is already stored in localstorage. With localstorage.getItem('user') I am able to show user values but did not use in key, when i display user values in console it give me message with undefined. Could you please help me how i can set key with userid.
Code
handleUpload = e => {
const reader = new FileReader();
const storeUser = JSON.parse(localStorage.getItem('user'));
reader.onload = function(upload) {
fetch(`http://...../s3/uploadtoaws`, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
method: 'POST',
body: JSON.stringify({
userId: storeUser._id,
type: 'employee',
content: upload.target.result,
key: this.userId,
oldKey: '',
}),
})
.then(response => response.json())
.then(res => {
console.warn(res);
})
.done();
};
reader.readAsDataURL(e.file.originFileObj);
};
Use window object to store your data if it is in-incentive
Like,
// Store like this..
window.user = {"_id": 1, "userName": "Bhavin00"};
// Use like this..
console.log(window.user);
or you can use npm package like :- reactjs-localstorage
let user = JSON.parse(localStorage.getItem('user'));
const { id: userId } = user;
Now you can use userId in the above request you shared.

How to post query parameters with Axios?

I am trying to post on an API with some query params.
This is working on PostMan / Insomnia when I am trying to by passing mail and firstname as query parameters :
http://localhost:8000/api/mails/users/sendVerificationMail?mail=lol%40lol.com&firstname=myFirstName
However, when I am trying to do it with my react native app, I got a 400 error (Invalid Query Parameters).
This is the post method :
.post(`/mails/users/sendVerificationMail`, {
mail,
firstname
})
.then(response => response.status)
.catch(err => console.warn(err));
(my mail and firstname are console.logged as follow: lol#lol.com and myFirstName).
So I don't know how to pass Query Parameters with Axios in my request (because right now, it's passing data: { mail: "lol#lol.com", firstname: "myFirstName" }.
axios signature for post is axios.post(url[, data[, config]]). So you want to send params object within the third argument:
.post(`/mails/users/sendVerificationMail`, null, { params: {
mail,
firstname
}})
.then(response => response.status)
.catch(err => console.warn(err));
This will POST an empty body with the two query params:
POST
http://localhost:8000/api/mails/users/sendVerificationMail?mail=lol%40lol.com&firstname=myFirstName
As of 2021 insted of null i had to add {} in order to make it work!
axios.post(
url,
{},
{
params: {
key,
checksum
}
}
)
.then(response => {
return success(response);
})
.catch(error => {
return fail(error);
});
In my case, the API responded with a CORS error. I instead formatted the query parameters into query string. It successfully posted data and also avoided the CORS issue.
var data = {};
const params = new URLSearchParams({
contact: this.ContactPerson,
phoneNumber: this.PhoneNumber,
email: this.Email
}).toString();
const url =
"https://test.com/api/UpdateProfile?" +
params;
axios
.post(url, data, {
headers: {
aaid: this.ID,
token: this.Token
}
})
.then(res => {
this.Info = JSON.parse(res.data);
})
.catch(err => {
console.log(err);
});
You can use params and body together in a request with axios
sendAllData (data) {
return axios
.post(API_URL + "receiveData", JSON.stringify(data), {
headers: { "Content-Type": "application/json; charset=UTF-8" },
params: { mail: xyx#example.col }, //Add mail as a param
})
.then((response) => console.log("repsonse", response.status));
}

Categories