Reputation: 1495
I'm using the fetch API in my react-native Android app to make requests to a local API. I usually query said API from react web apps at http://localhost:8163.
I'm testing my app on my physical device in debugger mode. I read somewhere that react-native can't query localhost the same way a web app can. Apparently you have to use http://10.0.2.2:[PORT_NUMBER_HERE]/
which is an alias for `http://127.0.0.1:[PORT_NUMBER_HERE] according to the Android emulator docks. I'm not sure if this is what I'm supposed to be doing for testing on a physical device.
My fetch code looks like the following:
fetchToken() {
fetch('http://10.0.2.2:8163/extension/auth', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-type': 'application/json'
}
})
.then((response)) => console.log('successful fetchToken response: ', response.json()))
.catch((error) => console.log('fetchToken error: ', error))
.done();
}
The request always hangs for a while and then reaches the catch
block with the unhelpful error TypeError: Network request failed(...)
. Checking the logs for my local API, they don't register the request at all.
So I have no idea if I'm querying my local API correctly to get the resource that I want, and if I am, I don't know why the fetch is failing.
Upvotes: 134
Views: 181125
Reputation: 1730
A 100% working solution that I'm using every time when I want to test an api locally with a mobile application:
Example: I'm exposing my localhost connected to port 8000:
ngrok http https://127.0.0.1:8000
In the terminal you'll get a generated link forwarding to the localhost: https://53fd-2c0f-f3a0-105-deff-5568-37c0-bcdb-72f7.ngrok-free.app
Example: https://53fd-2c0f-f3a0-105-deff-5568-37c0-bcdb-72f7.ngrok-free.app/api/auth
Upvotes: 5
Reputation: 1835
For Expo users
in expo app you can make your ip dynamic and it will be changed automatically when your machine ip changes by doing this.
import Constants from "expo-constants";
const { manifest } = Constants;
const uri = `http://${manifest.debuggerHost.split(':').shift()}:4000`; //this line will generate the your machine ip automatically
const response = await fetch(`${uri}/something`);
Upvotes: 1
Reputation: 1145
if localhost port is 8080
adb reverse tcp:8080 tcp:8080
if your port is something else then replace with 8080
Upvotes: 1
Reputation: 1830
This works like heaven
http://10.0.2.2:8080
instead of
http://localhost:8080
Upvotes: 5
Reputation: 101
In Android, we can use the IP 10.0.2.2 to access computers localhost.
const baseUrl = Platform.OS === 'android' ? 'http://10.0.2.2' : 'http://localhost';
Upvotes: 6
Reputation: 151
http or https based on it copy the URL
step 1: download ngrok unzip the package
step 2 :open ngrok.exe install it (or) double click on it terminal will be open
step 3:
ngrok http (port no of backend services)
eg:ngrok http 8081
step 4: copy url of https if it is https and then paste it in place of URL from UI.
Upvotes: 10
Reputation: 12592
In my case, I tried to make requests to http://localhost:3000
using axios but everytime I got Network Error
as a response. Then I found out that I need to make request to http://10.0.2.2:3000
in case of android simulator. For iOS simulator it works fine with http://localhost:3000
.
use
http://10.0.2.2:3000
instead of
http://localhost:3000
Better option is to map your computer's local server port to same port in device
$ adb devices
List of devices attached
emulator-5554 device <--- emulator
2681523e device <-- real device
$ adb -s emulator-5554 reverse tcp:3000 tcp:3000
$ adb -s 2681572e reverse tcp:3000 tcp:3000
You are done.
Upvotes: 81
Reputation: 101
I had the same issue and this solution worked for me:-
Step 1 : Get your IpV4 address by typing ipconfig
in your terminal
Step 2 : Host your API at your IpV4 address instead of localhost (for eg :- 192.168.0.106:3000
)
Step 3 : Run your API first
Step 4 : Fetch the data from the new address (for eg :- 192.168.0.106:3000
)
Step 5 : Only then start your app with react-native start or npm start
Upvotes: 1
Reputation: 2881
Good day, This is working
I use my machine's IP the Ethernet adapter Ethernet 2: IPV4 Address
And allow my port on firewall both Inbound and outbound rules
Upvotes: 3
Reputation: 76
Open the console in you're desktop, type : ipconfig
you'll get an IPv4_Address
and try this : 'http://IPv4_Address:8163/extension/auth'
Upvotes: 3
Reputation: 2206
If you're using expo just copy the URL above QR code and add it to you API instead localhost
it will like this
{
expo host :http://192.168.0.109:{Your Port}/The name for your API
}
Upvotes: 1
Reputation: 701
Run the below command to access localhost or 127.0.0.1 or your computer's ip
adb -s <device_name> reverse tcp:backend_port tcp:backend_port
Example:
adb -s emulator-5554 reverse tcp:3000 tcp:3000
Now, You can use like below in your component.
import React from 'react';
import {View,Image,TextInput, TouchableOpacity, StyleSheet, ImageBackground, AsyncStorage} from 'react-native';
import {Text,Button} from 'native-base';
export class Login extends React.Component{
constructor(props){
super(props);
this.state={username:'',password:''}
}
login = () =>{
fetch('http://localhost:3000/users',{
method:'POST',
headers:{
'Accept':'application/json',
'Content-Type':'application/json'
},
body:JSON.stringify({
username:this.state.username,
password:this.state.password
})
})
.then((response)=>response.json())
.then((res)=>{
if(res.success===true){
var username=res.message;
AsyncStorage.setItem('username',username);
this.props.navigation.navigate('app');
alert("Login success");
} else{
alert("Invalid Credentials");
}
})
.done();
}
render(){
return (
<View style={styles.content}>
<Text style={styles.logo}>- WELCOME -</Text>
<View>
<TextInput underlineColorAndroid='transparent' style={styles.input} placeholder="Username"
onChangeText={(username)=>this.setState({username})}
value={this.state.username}>
</TextInput>
<TextInput secureTextEntry={true} underlineColorAndroid='transparent' style={styles.input} placeholder="Password"
onChangeText={(password)=>this.setState({password})}
value={this.state.password}>
</TextInput>
</View>
<TouchableOpacity onPress={this.login} style={styles.buttonContainer}>
<Text style={styles.buttonText}>LOGIN</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
flex:1,
},
content:{
opacity:0.9,
backgroundColor:'white',
borderWidth:2,
margin:10,
alignItems: 'center',
},
logo:{
justifyContent: 'center',
alignItems: 'center',
fontSize:45,
color:'black',
textShadowColor:'gray',
textShadowRadius:10
},
input:{
borderRadius:10,
padding:10,
color:'black',
borderWidth:2,
borderColor:'lightgray',
width:200,
margin:5
},
buttonContainer:{
margin:10,
padding:10,
justifyContent: 'center',
alignItems: 'center',
},
buttonText:{
borderRadius:100,
padding:10,
backgroundColor:'magenta',
color:'white',
textAlign:'center',
width:100
}
});
Output:
Upvotes: 58
Reputation: 1
Maybe I'm late with the suggestion, but this helped me.
You should try http://0.0.0.0:8163/extension/auth
Upvotes: -1
Reputation: 69
If you are using Metro Bundler in Expo Developer Tools Use CONNECTION LAN ip address Sample image Metro Bundler
How to used in react native
getfetch = () => {
return fetch('http://LAN-IP-ADDRESS-HERE:4300/customers/',{
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
}
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
})
.catch((error) =>{
console.error(error);
});
}
Sample image REST API using postman
Hopefully this is helpful :)
Upvotes: 4
Reputation: 21
Had the same/similar issue - took me two full days to solve it. I use a Win10 machine with Visual Studio Code, attached Android device and a local PHP server for API. Maybe this will help somebody:
fetch('http://{your IP}:8081/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ message : responseJson.message.data })
})
.catch((error) => {
console.error(error);
});
Upvotes: 2
Reputation: 6136
You are not able to access your local development server because that port hasn't been forwarded by ADB yet. When you run react-native run-android
, React Native maps the port 8081 with your mobile device on USB. When you disconnect your USB you won't be able to refresh or hot reload your code anymore. So in this situation you can do 2 things, either map your local server port just like React Native does or use your local IP address.
Mapping Port
This only works if you are using Android 6.0+. To forward a port using ADB run the following command in your terminal:
adb reverse tcp:8163 tcp:8163
This will map your local 8163
port to mobile's 8163
port. You'll be able to access your development server this way.
Using local IP address
You can also use your local IP on React Native development app to reload them without USB. Shake your device or long press the menu button to open developer menu. Open Dev Settings
, then tap Debug server host & port for device
. Here you can enter your machine's local IP with port number 8081
. For ex. if your machine's IP is 192.168.1.100
then you'd enter 192.168.1.100:8081
in here for successful connection. Now we have covered that we can reload the app. After this when you want to use your local machine's development server use the same IP with your server's port number.
You should be good to go with this.
Upvotes: 195