Can't save state in React while POST API request - javascript

I have handleSubmit function that send two POST request, one for img upload and one for other information. I want to take the response from the img upload request and take the 'filename' and then store it in state so I can sent it with the other POST request.
Here is my Request Options
const postOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.serviceToken}`
},
body: JSON.stringify({
p_emp_id: empId,
p_pr_doc_type: docType,
p_from_date: fromDate,
p_to_date: toDate,
p_doc_number: docNumber,
p_addres: address,
p_addres_en: addressEN,
p_doc_store: docPath,
p_creator_id: creator,
p_org_id: org
})
};
Then here is my Handle Submit function
const handleSubmit = async (e) => {
e.preventDefault();
const data = new FormData();
data.append('file', selectedFiles);
await fetch(`${config.apiHost}single/`, {
method: 'POST',
body: data
})
.then((res) => res.json())
.then((img) => setDocPath(img.filename))
.catch((err) => {
console.log(err.message);
});
setEditOpen(false);
fetch(`${config.apiHost}api/employees/info/pr_docs/new/`, postOptions);
console.log(postOptions.body);
};
My state docPath stays empty while I'm trying to submit so after that I can't see it in my request.

you can refactor your code to this and lets see if it works;
let postOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.serviceToken}`
},
body: {
p_emp_id: empId,
p_pr_doc_type: docType,
p_from_date: fromDate,
p_to_date: toDate,
p_doc_number: docNumber,
p_addres: address,
p_addres_en: addressEN,
p_creator_id: creator,
p_org_id: org
}
};
for the handle submit it can be
const handleSubmit = async (e) => {
e.preventDefault();
const data = new FormData();
data.append('file', selectedFiles);
await fetch(`${config.apiHost}single/`, {
method: 'POST',
body: data
})
.then((res) => res.json())
.then((img) => {
const postOptionsBody = {...postOptions.body, p_doc_store : img.filename }
postOptions = {...postOptions, body : JSON.stringify(postOptionsBody) }
setDocPath(img.filename)
})
.catch((err) => {
console.log(err.message);
});
setEditOpen(false);
fetch(`${config.apiHost}api/employees/info/pr_docs/new/`, postOptions);
console.log(postOptions.body);
};

Related

unable to send form-data in react-native

I was using axios to send form-data in RN but it's not working. Noww tried fetch every feild uploads except images. If i use postman, everything works fine.
here is my code:
const postOrder = () => {
var data = new FormData();
data.append('marca', marca);
data.append('modeo', modeo);
data.append('option', option);
data.append('descripcion', descripcion);
data.append('images[]', images);
data.append('userId', '2');
dispatch(saveOrder(data));
};
fetch(`${baseUrl}/save-order`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
body: data,
})
.then(res => res.json())
.then(json => {
// dispatch({type: 'ORDER', payload: response.data});
console.log('json1', json);
})
.catch(error => {
console.log(error);
});
every property/feild is beig uploaded except images. I have tried these methods also
data.append('file', {
uri: images,
type: 'image/jpeg',
name: 'images[]',
});
data.append('file',images,'images[])
Axios didn't worked for me but fetch api did. here's my working code:
Post function
const postOrder = () => {
var data = new FormData();
data.append('marca', marca);
data.append('modeo', modeo);
data.append('option', option);
data.append('description', description);
data.append('images[]', {
uri: images,
name: 'image.jpg',
type: 'image/jpeg',
});
data.append('userId', state.user.id);
dispatch(saveOrder(data));
};
Fetch api
fetch(`${baseUrl}/save-order`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
body: data,
})
.then(res => res.json())
.then(json => {
console.log('json1', json);
})
.catch(error => {
console.log(error);
});
if You want to send multiple file do this
images.forEach((item, i) => {
data.append('images[]', {
uri: item.path,
type: item.mime,
name: item.path.slice(-8, -1) + 'g',
});
});
const formData = new FormData();
formData.append('file', {
uri: pictureUri,
type: 'image/jpeg',
name: 'profile-picture'
})
I had the same issue, Adding type: 'image/jpeg', to the file attribute of the formData fixed it.

Generate body for multipart file upload using fetch in Javascript

I am trying to upload a file(uploadType=multipart) to Drive API V3 using fetch but the body is wrong as it is creating a file with the title unnamed.
var tmpFile=document.getElementById('inputFile').files;
tmpFile=tmpFile[0];
await fetch('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart', {
method: 'POST', // or 'PUT'
headers: {
'Authorization': 'Bearer '+accessToken,
},
body: {
metadata:{
'name':tmpFile.name,
'Content-Type':'application/json; charset=UTF-8'
},
media:{
'Content-Type': '*/*',
'name':tmpFile
}
}
})
.then(response => response.json())
.then(data => {
console.log('Success:', data);
})
.catch((error) => {
console.error('Error:', error);
});
Your metadata is not being properly uploaded if its uploading with a name of unnamed
const fs = require("fs");
const FormData = require("form-data");
const fetch = require("node-fetch");
const filePath = "./sample.txt";
const accessToken = "###";
token = req.body.token;
var formData = new FormData();
var fileMetadata = {
name: "sample.txt",
};
formData.append("metadata", JSON.stringify(fileMetadata), {
contentType: "application/json",
});
formData.append("data", fs.createReadStream(filePath), {
filename: "sample.txt",
contentType: "text/plain",
});
fetch("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart", {
method: "POST",
body: formData,
headers: { Authorization: "Bearer " + accessToken },
})
.then((res) => res.json())
.then(console.log);
Uploading Files of multipart/form-data to Google Drive using Drive API with Node.js

react js fetch api using file upload not being sent to body

Here is my code
let formData = new FormData();
// Update the formData object
formData.append(
"myFile",
this.state.product_picture,
this.state.product_picture.name
);
var options = { content: formData };
const token = JSON.parse(localStorage.getItem('token'));
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
product_name:this.state.product_name,
product_description:this.state.product_description,
product_picture:formData,
category_name:this.state.category_choosen,
})
};
fetch('http://cms.test/api/products/insert_supplier_product?token='+token, requestOptions)
.then(response => response.json())
.then(data => {
this.setState({ product: data.product})
})
.catch(error =>{
console.log("Product creation error", error);
});
I have this fetch api its always giving a 422 response I think what is happening is that its not reading a file as I want to upload a file it all works in postman but when using react it crashes
The body here is the problem
inside the state there are some strings but inside the this.state.product_picture there is a file
Hope someone can help! Thank you!
SOLUTION: Using axios to call the api solved my problem
You cannot send a file in a JSON object in a request( atleast not without Base64 encoding it). Change your code in the following way to send a file with your form.
let formData = new FormData();
// Update the formData object
formData.append(
"myFile",
this.state.product_picture,
this.state.product_picture.name
);
formData.append("product_name",this.state.product_name);
formData.append("product_description",this.state.product_description);
formData.append("category_name",this.state.category_choosen);
var options = { content: formData };
const token = JSON.parse(localStorage.getItem('token'));
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData
};
fetch('http://cms.test/api/products/insert_supplier_product?token='+token, requestOptions)
.then(response => response.json())
.then(data => {
this.setState({ product: data.product})
})
.catch(error =>{
console.log("Product creation error", error);
});

Javascript node-fetch usage

I can get the data by request from this code.
let request = require('request');
let options = {
'method': 'POST',
'url': 'https://example.com/api',
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
form: {
'client_id': '12345678',
'client_secret': 'abcdefg'
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
However, I got '404.00.001' when I use "fetch" to access the same API. Is there any thing wrong in this code?
const fetch = require("node-fetch");
const url = "https://example.com/api";
var headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var data = JSON.stringify( {
'client_id': '12345678',
'client_secret': 'abcdefg'
});
fetch(url, {method: 'POST', headers: headers, body: data})
.then(response => response.json())
.then((resp) => {
console.log(resp);
})
.catch(error => console.error('Unable to fetch token.', error));
'Content-Type': 'application/x-www-form-urlencoded' does not say JSON so why do you have var data = JSON.stringify?
The documentation tells you how to encode data as form parameters.
const { URLSearchParams } = require('url');
const params = new URLSearchParams();
params.append('a', 1);

Getting different server response in Jquery $ajax and fetch in reactjs. Why aren't they the same?

$ajax server response:
{"username":"","password":""}
fetch server response:
{"{\"username\":\"\",\"password\":\"\"}":""}
Why aren't they the same? I need the same server response. I'm using PHP+Apache
Here is my code:
import $ from 'jquery';
export function FetchData(type, data){
const serverUrl = 'http://localhost/oms/'+ type + ".php";
return new Promise((resolve, reject) => {
$.ajax({
type: 'POST',
url: serverUrl,
data //body : {username: "username", password:"password"}
})
.done(function(res) {
//console.log(res);
resolve (res);
})
.fail(function(jqXHR, exception){
//alert('server error()');
reject(jqXHR);
});
fetch(serverUrl,{
method: 'POST',
headers: {
Accept: '*/*',
'Content-Type': 'application/x-www-form-urlencoded',
//'Access-Control-Allow-Origin': '*',
//'Access-Control-Allow-Methods': 'POST,GET,OPTIONS,PUT,DELETE',
//'Access-Control-Allow-Headers': 'Content-Type,Accept',
},
body: JSON.stringify(data)
//body : {username: data.username, password: data.password}
})
.then((response) => response.json())
.then((responseJson) => {
resolve(responseJson);
})
.catch((error) => {
reject(error);
});
});
}
The responses are essentially the same just that response from fetch library returns a Stringified JSON.
You need to convert it into actual JS object.
const responseData = JSON.parse(response.json())
This occurs because you're sending the content type application/x-www-form-urlencoded with JSON data you need to change it to application/json like
export const FetchData = (type, data) => {
let serverUrl = 'http://localhost/oms/'+ type + ".php";
let data = {
username: data.username,
password: data.password
};
return new Promise((resolve, reject) => {
fetch(serverUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
credentials: 'include',
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((responseJson) => {
resolve(responseJson)
})
.catch((error) => {
reject(error)
})
})
};
I added credentials it's read-only property of the Request interface indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests. This is similar to XHR’s withCredentials flag
If you want to use something smaller to jQuery you can use Axios It's XMLHttpRequests
If you get some CORS issues this will help you

Categories