React Native Android Fetch 在连接到本地 API 时失败

Posted

技术标签:

【中文标题】React Native Android Fetch 在连接到本地 API 时失败【英文标题】:React Native Android Fetch failing on connection to local 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 完成。 你解决了吗? 【参考方案1】:

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

    映射端口

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

    adb reverse tcp:8163 tcp:8163
    

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

    使用本地 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】:

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

结论

使用

http://10.0.2.2:3000

而不是

http://localhost:3000

更新

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

    查看已连接设备列表。可以是模拟器也可以是真机
$ 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 

你已经完成了。

【讨论】:

对我来说工作是一种简单而快速的解决方案,我只需要用我的后端端口更改端口。谢谢,兄弟【参考方案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 服务器。也许这会对某人有所帮助:

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

       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

【讨论】:

以上是关于React Native Android Fetch 在连接到本地 API 时失败的主要内容,如果未能解决你的问题,请参考以下文章

React Native Android - 第一次运行 react-native run-android 时出错

React Native - 在 Android 上构建 react-native-camera 错误

使用 react-native run-android 运行时出现 React-Native 错误

react-native run-android上的React Native错误

解决 React-Native: Android project not found. Maybe run react-native android first?

React Native 项目 Android Gradle 失败(React-Native-Reanimated Fail)