【问题标题】:React Native Android Fetch failing on connection to local APIReact Native Android Fetch 在连接到本地 API 时失败
【发布时间】:2016-02-15 16:57:51
【问题描述】:

我在我的 react-native Android 应用中使用 fetch API 向本地 API 发出请求。我通常在 http://localhost:8163 从 react web 应用程序中查询上述 API。

我正在我的物理设备上以调试器模式测试我的应用程序。我在某处读到 react-native 无法像 Web 应用程序那样查询 localhost。显然你必须使用http://10.0.2.2:[PORT_NUMBER_HERE]/,它是根据Android emulator docks 的`http://127.0.0.1:[PORT_NUMBER_HERE] 的别名。我不确定这是否是我在物理设备上测试时应该做的。

我的获取代码如下所示:

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();
}

请求总是挂起一段时间,然后到达catch 块,并出现无用的错误TypeError: Network request failed(...)。检查我的本地 API 的日志,他们根本没有注册请求。

所以我不知道我是否正确查询本地 API 以获取我想要的资源,如果是,我不知道为什么获取失败。

【问题讨论】:

  • 是的,那是因为您的 android 模拟器与本地开发计算机不同。对于物理设备,这就像在不同的机器上进行测试一样:要么拥有名称解析系统,要么使用 IP 地址
  • @njzk2 你能详细说明一下吗?我有同样的问题,但不确定名称解析系统是什么意思?我按照 react-native 文档中的要求使用计算机的 IP 地址..
  • @Andrea.cabral 名称解析通常由 DNS 完成。
  • 你解决了吗?

标签: android react-native


【解决方案1】:

您无法访问本地开发服务器,因为 ADB 尚未转发该端口。当你运行 react-native run-android 时,React Native 将端口 8081 映射到 USB 上的移动设备。当您断开 USB 时,您将无法再刷新或热重载您的代码。所以在这种情况下你可以做两件事,要么像 React Native 那样映射你的本地服务器端口,要么使用你的本地 IP 地址。

  1. 映射端口

    这仅在您使用 Android 6.0+ 时有效。要使用 ADB 转发端口,请在终端中运行以下命令:

    adb reverse tcp:8163 tcp:8163
    

    这会将您本地的8163 端口映射到手机的8163 端口。您将能够通过这种方式访问​​您的开发服务器。

  2. 使用本地 IP 地址

    您还可以在 React Native 开发应用程序上使用本地 IP 来重新加载它们而无需 USB。摇动您的设备或长按菜单按钮以打开开发者菜单。打开Dev Settings,然后点击Debug server host & port for device。在这里你可以输入你机器的本地 IP 和端口号8081。例如。如果您的机器的 IP 是 192.168.1.100,那么您将在此处输入 192.168.1.100:8081 以成功连接。现在我们已经介绍了我们可以重新加载应用程序。在此之后,当您想使用本地计算机的开发服务器时,请使用与服务器端口号相同的 IP。

你应该很好。

【讨论】:

  • 非常感谢您! adb反向救了我!起初我认为这是一个 http 与 https 的事情,并花了很长时间试图弄清楚如何设置我的 localhost API 以使用 https 而不是 http,结果一直都是这样。我不知道为什么我没有想到我的设备(即使它在模拟器中运行)默认情况下无法连接到我电脑上的 localhost:port。
  • 解决方案 1:不适合我 解决方案 2:不适合我可怜的我!
  • 我遇到了 ngrok。这是一个伟大的转发。一直在用它把我的本地 web api 暴露给外界。
  • 我为此困惑了好几天。不明白为什么我的应用程序会在 8081 上从 Metro 加载然后失败 request'n dev server @3000 模拟器的互联网似乎可以工作,但在登录时不在应用程序中。花了 40 多个小时,整整一周的工作,在各种方法上。我什至一度愚蠢地尝试adb reverse tcp:8081 tcp:8081,它会中断与捆绑器的连接,但直到我读到你说的地方我才连接点:[on]react-native run-android,React Native 将端口 8081 映射为USB 上的移动设备 非常感谢。对我来说adb reverse tcp:3000 tcp:3000 和繁荣。 ?
  • 解决方案 1 非常适合我。你用 Jason-proxy 和其他变通方法等不同的东西为我节省了 2 个小时的测试时间,谢谢!
【解决方案2】:

运行以下命令访问 localhost 或 127.0.0.1 或您计算机的 ip

adb -s <device_name> reverse tcp:backend_port tcp:backend_port

例子:

adb -s emulator-5554 reverse tcp:3000 tcp:3000

现在,您可以在组件中使用如下所示。

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
      }

    });

输出:

【讨论】:

  • 使用 127.0.0.1:8081 很重要,否则会抛出错误
  • 如果该端口已经在使用中会报错,否则不会报错。我只在linux中试过。所以,不知道windows还是mac。
  • 像魅力一样工作!!!
【解决方案3】:

就我而言,我尝试使用 axios 向 http://localhost:3000 发出请求,但每次我收到 Network Error 作为响应。然后我发现如果是android模拟器,我需要向http://10.0.2.2:3000提出请求。对于 iOS 模拟器,它适用于 http://localhost:3000

结论

使用

http://10.0.2.2:3000

而不是

http://localhost:3000

更新

更好的选择是将计算机的本地服务器端口映射到设备中的相同端口

  1. 查看已连接设备列表。可以是模拟器也可以是真机
$ adb devices                                   

List of devices attached
emulator-5554   device <--- emulator
2681523e        device <-- real device
  1. 映射端口
$ adb -s emulator-5554 reverse tcp:3000 tcp:3000

$ adb -s 2681572e reverse tcp:3000 tcp:3000 

你已经完成了。

【讨论】:

  • 对我来说工作是一种简单而快速的解决方案,我只需要用我的后端端口更改端口。谢谢,兄弟
【解决方案4】:

http or https based on it copy the URL

第一步:下载ngrok解压包

第2步:打开ngrok.exe安装它(或)双击它终端将打开

第 3 步

ngrok http (port no of backend services)
        
eg:ngrok http 8081

第 4 步:如果是 https,则复制 https 的 url,然后将其粘贴到 UI 中的 URL 位置。

【讨论】:

    【解决方案5】:

    在桌面打开控制台,输入:ipconfig

    你会得到一个 IPv4_Address

    试试这个:'http://IPv4_Address:8163/extension/auth'

    【讨论】:

    • 用法:ipconfig
    【解决方案6】:

    美好的一天, 这是有效的

    我使用我机器的IP以太网适配器Ethernet 2:IPV4地址

    并允许我的端口在防火墙上的入站和出站规则

    【讨论】:

      【解决方案7】:

      如果您在 Expo Developer Tools 中使用 Metro Bundler 使用 CONNECTION LAN ip 地址 Sample image Metro Bundler

      如何在 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);
          });
      }
      

      使用邮递员的示例图像 REST API

      Sample image POSTMAN

      希望这会有所帮助:)

      【讨论】:

        【解决方案8】:

        我遇到了同样的问题,这个解决方案对我有用:-

        • 第 1 步:通过在终端中输入 ipconfig 获取您的 IpV4 地址

        • 第 2 步:将您的 API 托管在您的 IpV4 地址而不是 localhost(例如:-192.168.0.106:3000

        • 第 3 步:首先运行您的 API

        • 第四步:从新地址获取数据(例如:-192.168.0.106:3000

        • 第 5 步:然后才使用 react-native start 或 npm start 启动您的应用

        【讨论】:

        • 用法:ipconfig
        【解决方案9】:

        遇到相同/相似的问题 - 我花了整整两天时间才解决它。我使用带有 Visual Studio Code 的 Win10 机器、附加的 Android 设备和用于 API 的本地 PHP 服务器。也许这会对某人有所帮助:

        1. 电缆 -> 尝试不同的 USB 电缆,在我的 3 根电缆中只有一根可以使用
        2. 连接模式 -> 非常重要,我必须选择 PTP 模式才能使其工作
        3. 同一个网络 -> 手机和电脑必须在同一个网络
        4. 私网 -> 网络必须是私网,公网不行
        5. IP -> 在 PowerShell 中运行 ipconfig 并获取您的 IP4 地址
        6. 防火墙 -> 接受防火墙提示
        7. PHP 服务器 -> 使用 "php -S {your IP}:8081" 启动内置 PHP 服务器
        8. 测试 PHP 服务器 -> 创建 index.php 并在手机上打开 {your IP}:8081
        9. 获取 -> 创建获取脚本(示例如下)

               fetch('http://{your IP}:8081/')
              .then((response) => response.json())
              .then((responseJson) => {
                this.setState({ message : responseJson.message.data })
                })
              .catch((error) => {
                console.error(error);
              }); 

        【讨论】:

          【解决方案10】:

          如果您使用 expo,只需复制 QR 码上方的 URL 并将其添加到您的 API 而不是 localhost

          会这样的

          {
            expo host :http://192.168.0.109:{Your Port}/The name for your API
          }
          

          【讨论】:

            【解决方案11】:

            尝试使用127.0.0.1 主机。 它对我有用。

            【讨论】:

              【解决方案12】:

              也许我的建议迟到了,但这对我有帮助。

              你应该试试http://0.0.0.0:8163/extension/auth

              【讨论】:

                猜你喜欢
                • 2021-12-29
                • 1970-01-01
                • 1970-01-01
                • 2015-07-06
                • 2018-06-16
                • 2019-10-06
                • 2019-09-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多