POST fails with ReadableNativeMap cannot be cast to String error - react-native

I'm working in React Native, I use PHP for backend and when I use fetch POST request I get so strange error, and I dont know why it happens. I checked the url so it works no problem, also normal fetch() is working without POST but when I try to post it happens. When I try it in local server fetch POST works.. but in server, I get this error :
ERROR : com.facebook.react.bridge.ReadableNativeMap cannot be cast to
java.lang.String
React native codes :
fetch('http://xxx/react_test1', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: inputName,
email: inputEmail,
phone: inputPhone
}),
}).then((response) => response.json())
.then((responseJson) => {
Alert.alert(responseJson);
}).catch((error) => {
alert(error);
});

Alert.alert receives an string, and what you're getting from the fetch response is internally a com.facebook.react.bridge.ReadableNativeMap object (which is what the native implementation for fetch returns).
You can try:
Alert.alert(JSON.stringify(responseJson))
If you were using iOS you'll get a completely different error:
Exception '-[_NSFrozenDictionaryM length]: unrecognized selector ...

Alert.alert only accepts string as input.
Use alert() instead to show the popup.
Example: alert("Response: ", responseJson)
Happy Coding. :)

So with fetch() in javascript you need headers: {} but when switching over to RNFetchBlob you should put the headers directly in the {}
import RNFetchBlob from "rn-fetch-blob";
const aPath = Platform.select({ ios: DocumentDir, android: DownloadDir });
const fPath = aPath + '/' + Math.floor(date.getTime() + date.getSeconds() / 2) + '.xls';
Also if you want to add body in the request then directly add it there.
For example:-
RNFetchBlob.config({
// response data will be saved to this path if it has access right.
path: fPath,
}).fetch('POST', URL, {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: token,
},
JSON.stringify(reqBody)
)
.then(res => {
console.log("response body>>>",res);
})
.catch(function (err) {
console.log(err);
});
that's all enjoy your coding...

Related

React Native: Fetching from API gives: Unexpected End Of JSON File

I am using React Native Expo and I am trying to fetch data from Fantasy API but when I parse the fetched data to JSON it says SyntaxError: Unexpected end of JSON input. This is the code I use for fetching:
fetch("https://fantasy.premierleague.com/api/bootstrap-static/", {
method: "GET",
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
})
.then((res) => {
return res.json();
})
.then((data) => {
console.log("DATA: ", data);
})
.catch((err) => {
console.log("Error: " + err);
});
Please add into consideration that the data is fetched properly when I use postman.
The provided code works for other APIs. I do not know why it does not work with this one.
Get request don't need headers so remove it and it will work.

Error trying to fetch access token from Spotify API using Axios

I'm working on a project with Vue using the Spotify API and get stuck trying to get the access token. I'm using axios to make the request but every time I get a 400 status from the server.
This is the way I'm doing it, I have the request inside an action in my Vuex store and I'm not sure if I'm missing something.
axios({
method: 'post',
url: 'https://accounts.spotify.com/api/token',
params: {
grant_type: 'authorization_code',
code: payload.code,
redirect_uri: process.env.VUE_APP_REDIRECT_URI
},
headers: {
'Authorization': 'Basic ' + (new Buffer(process.env.VUE_APP_CLIENT_ID + ':' + process.env.VUE_APP_CLIENT_SECRET).toString('base64')),
'Content-Type': 'application/x-www-form-urlencoded'
},
json: true
})
.then((response) => {
//handle success
resolve(response);
})
.catch((error) => {
//handle error
reject(error);
})
I would try using data instead of params.
I think data is for the POST body and params is for query string parameters.
Axios Cheat Sheet
You should inspect the request to see what you're sending and then compare that to what you should be sending.

Android: Network Request Failed when trying to upload image with fetch

I'm trying to upload an image from storage to a restful API but I keep getting Network Request Failed on Android (which means the request doesn't even go through), haven't checked on iOS because I don't need that part yet. API is already working and has been tested with Postman.
The React Native code is:
body.append('vehicles',{
resource_id: 2,
resource: 'vehicles',
cat_file_id: fileId,
active: 1,
vehicles: photo, //<- photo value below
name: 'vehicles',
type: 'image/jpeg'
})
fetch(`${BASE_URL}/files`, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
Accept: "*/*",
Authorization: 'Bearer '+auth
},
body: body
}).then(response => response.json())
.then(response => {
console.log('IMAGE RESPONSE', response)
})
.catch(error => console.log('ERROR', error))
The photo value looks like file:///storage/emulated/0/DCIM/...
The response:
ERROR TypeError: Network request failed
at XMLHttpRequest.xhr.onerror (fetch.umd.js:473)
at XMLHttpRequest.dispatchEvent (event-target-shim.js:818)
at XMLHttpRequest.setReadyState (XMLHttpRequest.js:574)
at XMLHttpRequest.__didCompleteResponse (XMLHttpRequest.js:388)
at XMLHttpRequest.js:501
at RCTDeviceEventEmitter.emit (EventEmitter.js:189)
at MessageQueue.__callFunction (MessageQueue.js:436)
at MessageQueue.js:111
at MessageQueue.__guard (MessageQueue.js:384)
at MessageQueue.callFunctionReturnFlushedQueue (MessageQueue.js:110)
On Postman the request looks something like this:
Already tried:
Removing Accept header
Changing Accept value to 'application/json'
Removing file:// from the image url
Added android:usesCleartextTraffic="true" to the manifest
Already checked:
No values are null or undefined
There is a working internet connection, all other network requests on the app are working fine
The Auth is correct
React Native version is 0.61.5
I found one missing line in your code let formData = new FormData();. but not sure is that the exact issue here.
By the way here is a sample working code from one of my project, and I customized it with your context.
Add your authentication
replace ImageURI with image path and URL_SAVE_IMAGE endpoint url
const newImage = {
resource_id: 2,
resource: 'vehicles',
cat_file_id: 1,
active: 1,
vehicles: ImageURI,
name: "my_photo.jpg",
type: "image/jpg",
};
let formData = new FormData();
formData.append("vehicles", newImage);
return fetch(URL_SAVE_IMAGE, {
method: 'POST',
headers: {
"Content-Type": "multipart/form-data"
},
body: formData
}).then(response => response.json());
it should work!
What is your fetch(${BASE_URL}/files` backend server .. This usually happens when trying to connect to the backend api on the localhost machine.. Even if you use the IP address of the localhost, it still persists, so it is better to use online server for testing or just use ngrok(https://ngrok.com/) to serve your backend localhost via internet.
in gradle.properties change the flipper version to 0.47.0
try with Xhr, it's working as expected!
const URL = "ANY_SERVER/upload/image"
const xhr = new XMLHttpRequest();
xhr.open('POST', url); // the address really doesnt matter the error occures before the network request is even made.
const data = new FormData();
data.append('image', { uri: image.path, name: 'image.jpg', type: 'image/jpeg' });
xhr.send(data);
xhr.onreadystatechange = e => {
if (xhr.readyState !== 4) {
return;
}
if (xhr.status === 200) {
console.log('success', xhr.responseText);
} else {
console.log('error', xhr.responseText);
}
};
Nothing worked for me except using the Expo FileSystem uploadAsync
uploadImage = async ({ imageUri } }) => FileSystem.uploadAsync(
apiUrl,
imageUri,
{
headers: {
// Auth etc
},
uploadType: FileSystem.FileSystemUploadType.MULTIPART,
fieldName: 'files',
mimeType: 'image/png',
});
Note - imageUri in format of file:///mypath/to/image.png
Happy days!

Post data to API in React Native only show empty

I am building an application in react native CRNA for the front-end side and using PHP for the backend side. But when I tried to post a data, for example login form, the result is only empty no matter what the given input is.
This is an example of my snippet code.
fetch('someURL', {
method: 'POST',
headers: {
"Content-Type": "application/json",
'Accept': 'application/json',
},
body: JSON.stringify({
name: this.state.name,
email: this.state.email,
message: this.state.message,
})
})
.then((response)=>response.json())
.then((responseData)=>{
Alert.alert(console.log(responseData))
return responseData;
}).catch((error) => {
console.error(error);
});
}
I tried to check the value with console.log and didn't get anything (only empty).. What should I do? Can anyone please tell me what's wrong? Thank you so much.
Try to remove the first then() and put the response.json() into the next then(). In the same block as the Alert.

How to check if body in fetch POST has sent to API in react native?

I am building a react native app and got this following error. I want to send inputted message, email, and name to API, but it's not showing any result in API.
Here is the code:
fetch('localserverusingIPaddress', {
method: 'POST',
headers: {
"Content-Type": "application/json",
'Accept': 'application/json',
},
body: JSON.stringify({
name: this.state.name,
email: this.state.email,
message: this.state.message,
}),
})
.then((response)=> {console.warn(response.json())})
//{
// if (response.status){
// return response.json();
// }
// console.warn(response.json())
// return response.json();
//})
//console.warn(response);
//response.json()
//console.warn(JSON.parse(response))})
.then((responseData)=>{
this.showAlert();
console.warn(responseData);
return responseData;
})
.catch((error) => {
console.warn(error);
});
However, when I try to check the inputted texts in iOS
simulator, it's showing the value. It's also showing the values when I post data to API directly with postman. So I start to think that the body was failed to pass to API.
Can anyone please tell me why is this happening and how to fix this? Thank you so much, I'm facing this problem for several weeks...
First step is to make sure if your iOS simulator is actually able to make requests to your localhost or not. If it can't reach your local network, it must throw some kind of connectivity error. However, from your comment above, it seems that is not an issue.
Try this code:
let url = 'localserverusingIPaddress';
let requestObject = {
name: this.state.name,
email: this.state.email,
message: this.state.message
};
try {
let response = await fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify(requestObject)
});
responseJson = await response.json();
console.log(responseJson);
} catch (error) {
console.error(error);
}
Try this and see what is the logged output.
Easiest way to see if the request has actually reached your API is from the API end itself. Your server must have some sort of event logging implemented. See what happens there when you make a request from Postman and compare its output with what happens when you make a request from the app.