React native axios is not working properly - react-native

I have this route on me BE
app.get('/welcomeRoute',(req,res)=> {
res.send("Hello world")
})
app.listen(4000,()=> {
console.log("Server is up")
})
I installed axios on my react native project with npm i axios , I created my project with expo init.
Here is how I use route
test = () => {
axios.get('http://localhost:4000/welcomeRoute').then((res)=> {
console.log('--------res', res);
}).catch((err)=> {
console.log('--------err', err);
})
}
Whenever i call this route i Always get --------err [Error: Network Error].
I tested this route in the postman and it is working fine.
Any suggestions please?

If the issue is on Android, the solution is to add below in in your AndroidManifest.xml file
android:usesCleartextTraffic="true"
In IOS, unencrypted network requests are blocked by default, i.e. https will work, http will not.
Your server from your emulator/device you need to access server via IP Address. Instead of http://localhost:port you should use http://your_ip_address:port

Actually in React Native you better give ip address of system rather than localhost because the device don't recognize your ip address using localhost

Related

How to make a fetch request to localhost in React Native/Expo?

I'm creating a React Native/Expo app that uses Deno on the backend. I've created an API in the backend that I can run locally on localhost:4000. When I try to use fetch to call the API in the Expo app, however, I keep getting an error
[Unhandled promise rejection: TypeError: Network request failed] at node_modules/whatwg-fetch/dist/fetch.umd.js:535:17 in setTimeout$argument_0
Here is how I set up the backend
import { Application } from "https://deno.land/x/oak/mod.ts";
import { oakCors } from "https://deno.land/x/cors/mod.ts";
import { APP_HOST, APP_PORT } from "./config.ts";
import router from "./routes.ts";
import _404 from "./controllers/404.ts";
import errorHandler from "./controllers/errorHandler.ts";
const app = new Application();
app.use(oakCors());
app.use(errorHandler);
app.use(router.routes());
app.use(router.allowedMethods());
app.use(_404);
console.log(`Listening on port:${APP_PORT}...`);
And how I use fetch to call the API
const App = () => {
const getData = async () => {
const response = await fetch("http://localhost:4000/something");
const data = await response.json();
console.log(data);
};
useEffect(() => {
getData();
}, []);
return (
...
);
};
Note
Some answers on StackOverflow suggest fetching http://[IP_ADDRESS]:4000/something instead of localhost. I've tried that with no luck.
I've verified that the API is working. I can call it successfully in VSCode's Thunder Client and I can also see the data by going to http://localhost:4000 in the browser.
I found a solution to this issue. I'm running my Expo app on a physical device while my server is running on my computer, on localhost. It makes sense that I'm unable to make requests to localhost on my device, because localhost is not running there.
I fixed this issue by using ngrok, a tool that forwards localhost to a cloud URL, and fetching that URL in the app.
Use the local IP assign to your device, like: http://192.168.20.109:port/api/x
find the local IP using the command "ipconfig" in windows or ifconfig in linux

React Native not allowing public route call to local strapi server

fairly new with strapi and react native. I created a strapi server and created a route that is public, with public authorization to find and find one(Which i'm guessing is the necessary ones to be public) that works perfectly fine if I call it on postman, even if I type it in the browser, and does not require any authorization or header, but when calling it from my react native app on android simulator it gives me a 401 error, which is strange because I can't find any other way I could possible make it more public, but I'm guessing I'm missing something has anyone had this problem?
Another thing that is strange is when running my react native in web it works fine... it's just on the android simulator
This is my call on my react native!
useEffect(() => {
const fetchAllUpdates = async () => {
await axios
.get(`http://localhost:1337/api/updates`, {
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => {
console.log('Data From Strapi ===>', res);
dispatch(setUpdates(res.data.data));
})
.catch((error) => console.log(`Strapi Error===> ${error}`));
};
fetchAllUpdates();
}, []);
Thank you in advance!
Ok I have figured it, the issue is that the android simulator does not have access to the local server the same way as the browser... so instead of calling
http://localhost:1337/api/updates
One has to find the machine ip address, and we can do that by typing
ipConfig
into the terminal and you will get your ip address then replace the
localhost
with the ip and it works
You should have something like this at the end
http://192.168.7.469:1337/api/updates

Unifying localhost dev api server access for expo app across Android, IOS, and web?

I'm setting up a simple React Native learning app for several students on Expo, that also talks to an API server the student is learning to code.
The student's API server is run via node server.js, and serves on localhost:3000 on the student's machine. It has nothing to do with expo.
I want students to be able to run their app via any of expo start --android, expo start --ios, or expo start --web, on the same machine that runs their API server. Each student runs from home on a different home wifi network, and doesn't necessarily know the ins and outs of ip addresses or networking.
When using expo start --web, we get CORS exceptions, unless we use the custom webpack.config.js work around (first create webpack.config.js via https://docs.expo.io/guides/customizing-webpack/, then put this in webpack.config.js):
const createExpoWebpackConfigAsync = require('#expo/webpack-config');
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
if (config.mode === 'development') {
config.devServer.proxy = {
'/**': {
target: {
host: 'localhost',
protocol: 'http:',
port: 3000,
},
secure: false,
changeOrigin: true,
logLevel: 'info',
},
};
}
return config;
};
This is great, because we can make api calls to ./end/point without knowing the student's ip address, and the webpack devServer launched by expo-cli effectively proxies around to http://localhost:3000/end/point on the student's development machine.
Meanwhile, for iOS and Android, I've found this snippet:
import Constants from "expo-constants";
const { manifest } = Constants;
const SERVER_URL = "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000`)+"/";
and then using SERVER_URL when using fetch().
But, we're missing a unified solution that works agnostic of which environment we're in (web, ios, or android). The webpack proxy only appears to be on and work when using the expo web client (expo-cli doesn't launch webpack for ios or android), and the 2nd option (A) doesn't work out of the box on web and (B) would trigger a CORS exception anyway.
How can I elegantly write one bit of code, or otherwise set up the project for the students, so that (A) they don't need to know their dev machine's ip address, or what that means and (B) it will work regardless of whether they're in the web, android, or ios expo client?
Don't like this as an answer and would prefer someone who knows better to point out better, but this is what I ended up using that seems to work, at least in development:
// Some chatter that Contants.manifest needs to come from a different package?
import Constants from "expo-constants";
const { manifest } = Constants;
const SERVER_URL = (() => {
// TODO - put a "prod" api server somewhere
// Android / IOS - no CORS issue.
if (!!manifest.debuggerHost) {
return "http://"+manifest.debuggerHost.split(`:`).shift().concat(`:3000/`);
}
// Expo Web client, making use of webpack.config.js (see original question) for devServer proxy.
else {
return "./";
}
})();
...
fetch(SERVER_URL + 'some_endpoint/').then(...)

Axios GET request resulting in CORS error

I'm working on a VueJS app, and I want to use the Yahoo! Shopping API (documentation: https://developer.yahoo.co.jp/webapi/shopping/shopping/v1/itemsearch.html) to fetch products using their barcode. However, I keep getting a CORS error and I'm not sure why, or what I can do to make it work. My code is as follows:
data() {
return {
appId: 'dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-',
apiUrl: 'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch'
}
}
...
axios.get(this.apiUrl, {
params: {
appid: this.appId,
jan: 4589707054951
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
alert(error)
})
The specific error I get is this:
Access to XMLHttpRequest at
'https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch?appid=dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-&jan=4589707054951'
from origin 'https://0.0.0.0:8080' has been blocked by CORS policy: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
What can I do to make this work? So far the only way it works is using the CORS Chrome extension, but that's naturally just for testing.
Thanks a lot.
The server/api owner needs to send this in his response header:
Or if you have a server settings panel or something, make sure to add the domain from where you are making the request.
Access-Control-Allow-Origin: 'your-domain-here'.
Please read more at: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I got the same error. I solved it in the following manner.
This error occurs because we are tryign to access the data hosted on a different server. CORS issue is a browser issue where a certain browser does allow you to access the contents hosted on a different or a virtual server. If you observe the app that you are running on is on the local-host (https://0.0.0.0:8080) and trying to access the data hosted on https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch. You can solve this problem simply by adding in a few lines of code in your vue application.
Step 1:
Create a new file called vue.config.js in your root directory of the vue application, that is beside your package.json file. Add the following code in your vue.config.js file:
module.exports = {
devServer:{
proxy: "https://shopping.yahooapis.jp"
}
}
Note: https://shopping.yahooapis.jp would be your base url.
Step 2:
Now, go back to your code in data(). Replace the domain name/base url of the apiUrl with https://0.0.0.0:8080. that is now your apiUrl would be https://0.0.0.0:8080/ShoppingWebService/V1/json/itemSearch.
data() {
return {
appId: 'dj00aiZpPUQ4RTBUUTVSNUs3TyZzPWNvbnN1bWVyc2VjcmV0Jng9NTI-',
apiUrl: 'https://0.0.0.0:8080/ShoppingWebService/V1/json/itemSearch'
}
}
Step 3:
Restart your application. Eg, npm run serve.
I found another solution which worked without creating a proxy server or a mock server. You can disable the security settings for accessing cross origin apis on your web browser.
You can disable the CHROME security settings for accessing apis out of the origin by typing the below command on the terminal:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir="/tmp/chrome_dev_session" --disable-web-security
After running the above command on your terminal, a new chrome window with security settings disabled will open up. Now, run your program (npm run serve / npm run dev) again and this time you will not get any CORS error and would be able to GET request using axios.
Hope this helps!

Access Dyson server from React Native ios

I'm using Dyson to host a little mock server for my React Native app, and trying to fetch from the server. The server appears to be running well and when I visit my desired url, http://localhost:3000/stations, in my browser, I get a nice JSON response.
In my React Native action, though, I get Network request failed:
export function fetchStations() {
return dispatch => {
dispatch({ type: "GET_STATIONS_START" });
fetch("http://localhost:3000/stations")
.then(res => {
return res.json();
})
.then(json => {
dispatch({ type: "GET_STATIONS_SUCCESS", payload: json.stations });
})
.catch(error => {
console.warn(error);
dispatch({ type: "GET_STATIONS_FAILURE", payload: error });
});
};
}
Using a static local URL works, and using, say, the Google Maps API works (even though it's not what I want, it's just a sample API to try).
I would think I may be calling the url wrong but it works in the browser so that seems doubtful. My guess is that is has something to do with iOS not liking http requests (only accepting https), unless you set some setting somewhere (I've been through this in native iOS development).
If this is the problem, how do I fix it from React Native? Or, what is the actual problem?
PS. I'm using dyson rather than json-server because for some reason I can't get json-server to work. See my other post. Somewhere here :)
I figured it out. The device (simulator) doesn't have access to localhost so I had to set my url to http://127.0.0.1:3000/stations and it works like a dream.