網站搜尋

javascript - React Native fetch() 網路請求失敗


當我使用 react-native init(RN 版本 0.29.1)創建一個全新的專案,並在 render 方法中放置一個對公共 Facebook 範例電影 API 的 fetch 時,它會拋出 Network Request Failed。有一個非常無用的堆疊追蹤,並且我無法在 Chrome 控制台中調試網絡請求。這是我發出的 fetch:

fetch('http://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => {
        return responseJson.movies;
      })
      .catch((error) => {
        console.error(error);
      });

答案#1

這裡的問題是 iOS 預設不允許 HTTP 請求,只允許 HTTPS。如果你想啟用 HTTP 請求,請將以下內容添加到你的 info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

答案#2

我使用的是 localhost 作為地址,但這顯然是錯的。將它替換為伺服器的 IP 地址(在模擬器所在的網路中)後,它工作得非常完美。

編輯

在 Android 模擬器中,開發機的地址是 10.0.2.2。更多說明請參見這裡

對於 Genymotion,地址是 10.0.3.2。更多資訊在這裡

答案#3

不建議允許所有網域使用 http。僅對必要的網域例外處理。

來源:在 iOS 9 和 OS X 10.11 中配置應用傳輸安全例外

將以下內容添加到您應用程式的 info.plist 文件中:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

答案#4

我在 Android 9 上遇到了相同的問題,原因是「http」,問題通過只在 AndroidManifest.xml 中添加 android:usesCleartextTraffic="true" 得到了解決。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
  android:usesCleartextTraffic="true"
 .......>
 .......
</application>

答案#5

對我們來說,原因是我們正在上傳一個文件,而 RN filePicker 沒有提供正確的 mime 類型。它只給了我們 'image' 作為類型。我們需要將其更改為 'image/jpg' 才能讓 fetch 正常工作。

form.append(uploadFileName, {
  uri : localImage.full,
  type: 'image/jpeg',
  name: uploadFileName
 })

答案#6

如果你使用本地主機,只需更改它:

從:http://localhost:3030 到:http://10.0.2.2:3030

答案#7

我在 Android 上也遇到了同樣的問題,但我設法找到了解決方法。從 API Level 28 開始,Android 默認會阻擋明文流量(非 HTTPS 請求)。然而,react-native 在調試版本中添加了一個 network-security-config(android/app/src/debug/res/xml/react_native_config.xml),其中定義了一些域名(localhost,以及 AVD/Genymotion 的主機 IP),這些域名在開發模式下可以不使用 SSL。你可以將你的域名添加到那裡以允許 HTTP 請求。

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="false">localhost</domain>
    <domain includeSubdomains="false">10.0.2.2</domain>
    <domain includeSubdomains="false">10.0.3.2</domain>
    <domain includeSubdomains="true">dev.local</domain>
  </domain-config>
</network-security-config>

答案#8

適用於 Android 用戶:

  1. 將 localhost 替換為局域網 IP 地址,因為當你在 Android 設備上運行專案時,localhost 指向的是 Android 設備,而不是你的電腦,例如:將 http://localost 改為 http://192.168.1.123

  2. 如果您的請求 URL 為 HTTPS 且您的 Android 設備位於代理下,假設您已在 Android 設備上安裝了用戶添加的 CA(例如 Burp Suite 的 CA 或 Charles 的 CA),請確保您的 Android 版本低於 Nougat(7.0),因為:Android Nougat 中受信任的證書權限變更

    使用者新增的憑證授權 (CA)
    保護所有應用程式資料是 Android 應用程式沙盒的一個重要目標。Android Nougat 改變了應用程式與使用者及管理員提供的 CA 的互動方式。預設情況下,針對 API 級別 24 的應用程式設計上不會認可這些 CA,除非應用程式明確選擇啟用。這種預設安全設定降低了應用程式的攻擊面,並鼓勵對網路及檔案型應用程式資料的一致處理。

答案#9

React Native 文件提供了這個問題的答案。

蘋果已經阻止了隱式明文 HTTP 資源加載。因此我們需要將以下內容添加到我們專案的 Info.plist(或等效)文件中。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost</key>
        <dict>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

React Native 文件 -> 與現有應用整合 -> 測試您的整合 -> 添加應用傳輸安全例外

答案#10

問題可能出在伺服器配置上。

Android 7.0 有一個在這裡描述的錯誤。Vicky Chijwani 提出的解決方法:

將您的伺服器配置為使用橢圓曲線 prime256v1。例如,在 Nginx 1.10 中,您可以通過設置 ssl_ecdh_curve prime256v1; 來實現這一點。

答案#11

我在 Android 上遇到這個問題。

URL- localhost/authToken.json - 不管用 :(

URL- 10.106.105.103/authToken.json - 無法使用 :(

URL- http://10.106.105.103/authToken.json - 成功了 :) :D

注意-在 Linux 上使用 ifconfig 或在 Windows 上使用 ipconfig 來查找機器的 IP 位址