Can't get `fetch()` working in React Native - react-native

Any idea why I can't get fetch() working in React Native? Full code is here on RN Play:
https://rnplay.org/apps/L80w2w
Here's a working ReactJS Fiddle that I'm trying to get working in React Native: https://jsfiddle.net/ssorallen/fEsYt/
componentDidMount: function() {
var _this = this;
var queryParams = "fn" + Date.now() + '/';
var queryUrl = "https://www.reddit.com/reddits.json?jsonp=" + queryParams;
fetch(queryUrl)
.then(response => response.json())
.then(responseData => this._handleResponse(responseData.data.children))
.catch(error => this.setState({
isLoading: false,
errorMessage: 'Something bad happened - loading navigationItems: \n' + error
}));
},
_handleResponse(results) {
this.setState({ isLoading: false });
if (results.length > 0) {
this.setState({
navigationItems: results
});
} else {
this.setState({ errorMessage: "Can't find JSON." });
}
},

You are attempting to call the Reddit using the JSONP technique, which is not necessary, as React Native does not impose the Same-Origin security policy as browsers do.
If you remove the ?jsonp=" + queryParams parameter from your URL, the requests should work.

completed = (id) => {
var details = {
'id': id,
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
fetch(markcompleted, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formBody
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson, 'res JSON');
if (responseJson.status == "success") {
console.log(this.state);
alert("your todolist is completed!!");
}
})
.catch((error) => {
console.error(error);
});
};
#change post into get

Related

Sending a PUT request with Spotify's WebAPI returns a 401 error

What I want to do
I want to change the playlist image using Spotify's API.
API reference:https://developer.spotify.com/documentation/web-api/reference/#/operations/upload-custom-playlist-cover
Problem
API request returns 401 error.
Access token is fine.
Other requests using the same axios instance (spotify_api) are fine.
Even if the access token is invalid, the process of reissuing and repeating the previous request runs.
My Code
home.vue
import spotify_api from "../../util/spotify_api";
import fivetune_api from "../../util/fivetune_api";
let fi_user_id = "";
let sp_user_id = "";
let access_token = "";
export default {
data() {
return {
playlists: [],
tracks: [],
track: {
no: 1,
artist: "",
artist_url: "",
album_url: "",
track_name: "",
track_image_url: "",
track_url: "",
},
};
},
name: "Home-1",
props: {
msg: String,
},
async created() {
fi_user_id = this.$cookies.get("fi_user_id");
access_token = this.$cookies.get("access_token");
await fivetune_api.get("/api/user/" + fi_user_id).then((res) => {
sp_user_id = res.data.sp_user_id;
});
fivetune_api.get("/api/playlist/home").then(async (res) => {
this.playlists = res.data;
for (let i = 0; i < this.playlists.length; i++) {
this.tracks = [];
await Promise.all([
spotify_api.get("/users/" + this.playlists[i].sp_creator_user_id),
fivetune_api.get("/api/download/" + this.playlists[i].fi_playlist_id),
])
.then((res2) => {
this.playlists[i].creator_name = res2[0].data.display_name;
this.playlists[i].download_count = res2[1].data[0].download_count;
})
.catch((err) => {
console.log(err);
console.log(access_token);
// access_token = refreshToken(err);
});
for (let j = 0; j < this.playlists[i].track_ids.length; j++) {
await spotify_api
.get("/tracks/" + this.playlists[i].track_ids[j].sp_track_id)
.then((res_track) => {
this.track = {
no: j + 1,
track_id: res_track.data.id,
artist: res_track.data.artists[0].name,
artist_url: res_track.data.artists[0].external_urls.spotify,
album_url: res_track.data.album.external_urls.spotify,
track_name: res_track.data.name,
track_image_url: res_track.data.album.images[0].url,
track_url: res_track.data.external_urls.spotify,
};
this.tracks.push(this.track);
})
.catch((err) => {
console.log(err);
// access_token = refreshToken(err);
});
}
this.playlists[i].tracks = this.tracks;
this.playlists[i].playlist_image =
process.env.VUE_APP_HOST +
"/images/playlist/" +
this.playlists[i].fi_playlist_id +
".jpeg";
}
});
},
methods: {
download: async function (index) {
const track_1 = document.getElementById(
`playlist-${index}-track-0-id`
).value;
const track_2 = document.getElementById(
`playlist-${index}-track-1-id`
).value;
const track_3 = document.getElementById(
`playlist-${index}-track-2-id`
).value;
const track_4 = document.getElementById(
`playlist-${index}-track-3-id`
).value;
const track_5 = document.getElementById(
`playlist-${index}-track-4-id`
).value;
const fi_playlist_id = document.getElementById(
`playlist-${index}-id`
).value;
const playlist_name = document.getElementById(
`playlist-${index}-playlist-name`
).innerHTML;
///////////////////////////////////////////////////////////////////////////////////////////////////
////// this //////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
spotify_api
.post("/users/" + sp_user_id + "/playlists", {
name: playlist_name,
description: "",
public: false,
})
.then(async (res) => {
const created_playlist_id = res.data.id;
spotify_api
.put("/playlists/" + created_playlist_id + "/images", {
data: this.playlists[index].img_base64
})
.then(() => {})
.catch((err) => {
console.log(err);
});
///////////////////////////////////////////////////////////////////////////////////////////////////
////// end //////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
await Promise.all([
spotify_api.post("/playlists/" + created_playlist_id + "/tracks", {
uris: [
"spotify:track:" + track_1,
"spotify:track:" + track_2,
"spotify:track:" + track_3,
"spotify:track:" + track_4,
"spotify:track:" + track_5,
],
}),
])
.then(() => {
fivetune_api
.post("/api/download", {
fi_user_id: fi_user_id,
fi_playlist_id: fi_playlist_id,
})
.then(() => {
this.playlists[index].download_count += 1;
this.$swal.fire({
title: "ダウンロード完了",
html: "Spotifyのプレイリストに追加されました。",
confirmButtonColor: "#8db30f",
});
})
.catch((err) => {
console.log(err);
});
})
.catch((err) => {
console.log(err);
this.$swal.fire({
title: "ダウンロード失敗",
confirmButtonColor: "#8db30f",
});
});
});
},
},
};
spotify_api.js(
An instance of axios is created)
import axios from 'axios';
const spotify_api = axios.create({
baseURL: 'https://api.spotify.com/v1',
withCredentials: false,
})
let refresh_token_promise;
const getRefreshToken = () => {
return new Promise((resolve) => {
console.log(300)
axios.get('/api/refresh').then((res) => {
const access_token = res.data
return resolve(access_token)
}).catch((err) => {
console.log('err 2')
console.log(err)
})
})
}
spotify_api.interceptors.request.use(req => {
req.headers = {
authorization: `Bearer ${localStorage.getItem('access_token')}`,
"Content-Type": "application/json",
}
return req
})
spotify_api.interceptors.response.use((res) => {
return res
}, (err) => {
if (err.config && err.response && err.response.status === 401 && !err.config._retry) {
console.log(100)
if (!refresh_token_promise) {
err.config._retry = true;
refresh_token_promise = getRefreshToken().then((token) => {
refresh_token_promise = null;
console.log(token)
localStorage.setItem('access_token', token)
return token
}).catch((err) => {
console.log('err')
console.log(err)
})
}
console.log(200)
return refresh_token_promise.then((access_token) => {
const config = err.config;
config.headers = {
authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
}
return axios.request(config)
}).catch((err) => {
console.log(err)
})
}
return Promise.reject(err)
})
export default spotify_api
What I tried
I tried various names of the body requesting the image
( data、image、postData )
I tried setting Content-Type to image/jpeg
I wrote it directly without using axios instant.
await axios
.put(
"https://api.spotify.com/v1/playlists/" +
created_playlist_id +
"/images",
{
data: this.playlists[index].img_base64,
headers: {
authorization: `Bearer ${localStorage.getItem(
"access_token"
)}`,
"Content-Type": "application/json",
},
}
)
.then((res_image) => {
console.log("res_image");
console.log(res_image);
})
.catch((err) => {
console.log("err");
console.log(err);
});
Environment
FrontEnd
Vue.js3
BackEnd
Node.js

How to upload a file in react-native iOS?

While trying to upload a file I ran into an issue on iOS, the code works fine on android. After a bit of googling, I found that it is a known issue in react-native iOS and has a bug report submitted. This is the issue. I want to know if there is any other way to upload files on iOS. Below is the snippet of code I'm using. Please let me know if there is something that can be done.
const resp = await fetch(uploadUrl, {
method: 'POST',
headers: {
'content-type': 'multipart/form-data',
},
body: file, // file is File type
});
You can something like below code snippet
function uploadProfileImage(image, token) {
const url = ServiceUrls.UPLOAD_PROFILE_IMAGE
return uploadResourceWithPost({
url,
authToken: token,
formData: createFormData(image),
})
}
const createFormData = (data) => {
const form = new FormData()
form.append('file', {
uri: Platform.OS === 'android' ? data.uri : data.uri.replace('file://', ''),
type: 'image/jpeg',
name: 'image.jpg',
})
return form
}
const uploadResourceWithPost = ({ url, authToken, formData }) => {
return handleResponse(axios.post(url, formData, defaultUploadOptions(authToken)))
}
const defaultUploadOptions = (authToken) => ({
timeout,
headers: {
'X-Auth-Token': authToken,
'Content-Type': 'multipart/form-data',
},
})
const handleResponse = (responsePromise) => {
return NetInfo.fetch().then((state) => {
if (state.isConnected) {
return responsePromise
.then((response) => {
return ResponseService.parseSuccess(response)
})
.catch((error) => {
return ResponseService.parseError(error)
})
}
return {
ok: false,
message: 'Check your network connection and try again.',
status: 408,
}
})
}
const parseSuccess = ({ data, headers }) => ({ ...data, headers, ok: true })
const parseError = ({ response }) => {
let message = 'Check your network connection and try again.'
let status = 408
if (response && response.data) {
const { data } = response
message = data.message
status = data.code
}
return { status, message }
}

React Native - fetch API error: [SyntaxError: JSON Parse error: Unexpected identifier "object"]

Newbie to React Native. I am trying to use FormData to upload image and data using the fetch API following example from Spencer Carli. My back end works fine, when I use postman the image uploads to the database storage without any problem. But when I try to upload image via the mobile device I get
upload error [SyntaxError: JSON Parse error: Unexpected identifier "Tunnel"]
Below is my code
const createFormData = (photo, body) => {
const data = new FormData();
data.append('file', {
name: photo.fileName,
type: photo.type,
uri:
Platform.OS === 'android' ? photo.uri : photo.uri.replace('file://', ''),
});
Object.keys(body).forEach(key => {
data.append(key, body[key]);
});
return data;
};
const uploadPhotoHandler = async (photo) => {
const token = await AsyncStorage.getItem('token');
fetch('http://ba9737b7.ngrok.io/post', {
headers: {'Authorization': 'Bearer ' + token},
method: 'POST',
body: createFormData(photo, {
title: 'Golden twisted knots',
postType: 'hair',
duration: 45}),
})
.then(response => response.json())
.then(response => {
console.log('upload succes', response);
alert('Upload success!');
})
.catch(error => {
console.log('upload error', error);
alert('Upload failed!');
});
};
I think the problem is from this line
.then(response => response.json())
but I don't know why.
The problem is because you are not getting a JSON response. When you are trying to parse to JSON.
You can solve it checking first the response status code, try this.
const uploadPhotoHandler = async (photo) => {
const token = await AsyncStorage.getItem('token');
fetch('http://ba9737b7.ngrok.io/post', {
headers: {'Authorization': 'Bearer ' + token},
method: 'POST',
body: createFormData(photo, {
title: 'Golden twisted knots',
postType: 'hair',
duration: 45}),
})
.then(response => {
//If the response status code is between 200-299, if so
if(response.ok) return response.json();
//if not, throw a error
throw new Error('Network response was not ok');
})
.then(response => {
console.log('upload succes', response);
alert('Upload success!');
})
.catch(error => {
console.log('upload error', error);
alert('Upload failed!');
});
};

How to get Html code by fetching web API response?

When we are trying to fetch html code via fetch API response but we are enable to get it because it return "Unexpected Token <"
onLoginService2 = async () => {
try {
var hittingURl = "https://members.iracing.com/membersite/Login?username=dave#rms55.com.au&password=rms55Pa55&utcoffset=-600&todaysdate=1558055491688&checkbox=0";
const myRequest = new Request(hittingURl.toString(),
{
method: 'POST',
headers: {
'Accept': 'text/html',
'Content-Type': 'text/html;charset=ISO-8859-1',
},
timeout: 1000,
// body: JSON.stringify("")
}
);
fetch(myRequest)
.then((response) => console.log("abcdefghijklmon--> "+JSON.stringify(response)))
.then((data) => {
console.log("RESPONSERR----> ",data+"");
// this.setState({ isLoading: false })
// this.onLoginSuccessFull(responseJson)
})
.catch((error) => {
this.setState({ isLoading: false })
console.log("response--31" + error);
})
} catch{
}
// }
}
The response of first then has a method .text(), which return Promise
Try this
fetch(myRequest)
.then(resp => resp.text())
.then(text => {
//text is html
})
*Just copy the above and run in console to see the result.

fetch response.json() gives responseData = undefined

When using fetch:
fetch(REQUEST_URL, {
method: 'get',
dataType: 'json',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then((response) =>
{
response.json() // << This is the problem
})
.then((responseData) => { // responseData = undefined
console.log(responseData);
});
}).catch(function(err) {
console.log(err);
})
.done();
The following works works, do you know why? :
JSON.parse(response._bodyText)
The chaining response should look more like this, specifically the response.json part. Then you should get an Object back in console.log.
.then(response => response.json())
.then(response => {
console.log(response)
}
Fetch is a little hard to get your head around. I am new to this so dont shoot me down if flames here but response data is another promise and you need to return response data and then handle that promise with yet another then statement where you can finally log the response, also your are missing some return statements in your promises:
var makeRequest = function(){
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'get',
dataType: 'jsonp',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then((response) => {
return response.json() // << This is the problem
})
.then((responseData) => { // responseData = undefined
addTestToPage(responseData.title);
return responseData;
})
.catch(function(err) {
console.log(err);
})
}
function addTestToPage(textToAdd){
var para = document.createElement("p");
var node = document.createTextNode(textToAdd);
para.appendChild(node);
var element = document.getElementsByTagName("body")[0];
element.appendChild(para);
}
makeRequest();
hope that helps see: https://jsfiddle.net/byz17L4L/
Here's how it finally worked out in my case:
fetch('http://localhost:3001/questions', {
method: 'GET',
headers: {
"Accept": "application/json",
'Content-Type': 'application/json'
}
})
.then(response => { return response.json();})
.then(responseData => {console.log(responseData); return responseData;})
.then(data => {this.setState({"questions" : data});})
.catch(err => {
console.log("fetch error" + err);
});
}
because you didn't return response.json() in the first then.
import React, {useEffect} from 'react';
useEffect(() => {
getRecipes();
}, []);
const getRecipes = async () => {
const response = await fetch(
`https://........`
);
const data = await response.json();
console.log(data);
Use this method You can easily fatch data.
fetch(weatherIng + zipCode +apiKey)
.then(response => response.json())
.then(response => {
console.log(response.main);
this.setState({
weather: ((response.main.temp * (9/5))-459.67).toFixed(0),
humidity:((response.main.humidity * (9/5))-459.67).toFixed(0)
})
It will think that you are trying to declare something if you don't enclose it in its own:
.then(response => {
console.log(response.main);
}) . " around the this.setState