React-native IOS: Network request failed

2019-02-22 07:22发布

问题:

I'm testing a react native app (on OS X Yosemite in the xcode simulator v9.2 / xcode 7.2.1). I'm getting a Network request failed error with the below code. The actual url with the correct appid works just fine in a browser and gives me the correct information in json format, and the promise / api call looks fine.

I'm not behind a firewall. I've tried troubleshooting the connection, and activating the Allow HTTP Services in the Developer settings, but I'm still getting the error.

Any idea what the problem is here? The actual errors are as follows:

-- There has been a problem with your fetch operation: Network request failed
-- Api call error =  Network request failed

Here's the api.js code:

var _ = require('lodash');
var rootUrl = 'http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxxxxxxxxxxxxxxxxxx';

var kelvinToF = function(kelvin) {
  return Math.round((kelvin - 273.15) * 1.8 + 32) + ' ˚F'
};

var kelvinToC = function(kelvin) {
  return Math.round(kelvin - 273.15) + ' ˚C'
};  

module.exports = function(latitude, longitude) {
  var url = `${rootUrl}&lat=${latitude}&lon=${longitude}`;
  console.log(url);
  return fetch(url)
    .then(function(response){
      return response.json();
    })
    .then(function(json){
      return {
        city: json.name,
        temperature1: kelvinToF(json.main.temp),
        temperature2: kelvinToC(json.main.temp),
        description: _.capitalize(json.weather[0].description)
      }
    })
    .catch(function(error) {
    console.log('There has been a problem with your fetch operation: ' + error.message);
    throw error;
});
}

Here's the index.ios.js code.

/*  --depreciated

var React = require('react-native'); 

var {
  AppRegistry,
  MapView,
  View,
  Text,
  StyleSheet
} = React;
*/ 


// updated
import React from 'react';

// updated
import {
  AppRegistry,
  MapView,
  View,
  Text,
  StyleSheet,
} from 'react-native';

var Api = require('./src/api');

var Weather = React.createClass({
  getInitialState: function() {
    return {
      pin: {
        latitude: 0,
        longitude: 0
      },
      city: '',
      temperature1: '',
      temperature2: '',
      description: ''
    };
  },
  render: function() {
    return <View style={styles.container}>
      <MapView
        annotations={[this.state.pin]}
        onRegionChangeComplete={this.onRegionChangeComplete}
        style={styles.map}>
      </MapView>
      <View style={styles.textWrapper}>
        <Text style={styles.text}>{this.state.city}</Text>
        <Text style={styles.text}>{this.state.temperature1}</Text>
        <Text style={styles.text}>{this.state.temperature2}</Text>
        <Text style={styles.text}>{this.state.description}</Text>
      </View>
    </View>
  },
  onRegionChangeComplete: function(region) {
    this.setState({
      pin: {
        longitude: region.longitude,
        latitude: region.latitude
      }
    });

    Api(region.latitude, region.longitude)
      .then((data) => {
        console.log(region.latitude);
        console.log(region.longitude);
        console.log('data = ' + data);
        this.setState(data);
      })
      .catch((error)=>{
     console.log("Api call error = ", error.message);
    // alert(error.message);     
  });
  }
});


var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'stretch',
    backgroundColor: '#F5FCFF'
  },
  map: {
    flex: 2,
    marginTop: 30
  },
  textWrapper: {
    flex: 1,
    alignItems: 'center'
  },
  text: {
    fontSize: 30
  }
});

AppRegistry.registerComponent('weather', () => Weather);

回答1:

You will need to change your NSAppTransportSecurity policy in info.plist. By default in ios 8 and greater plaintext request are blocked. See Transport security has blocked a cleartext HTTP



回答2:

Ok thanks to @while1's answer above, I found the answer that worked for me. The code in my question above is fine. I had to change the info.plist file. Wow what a pain in the ass apple are, why would they complicate things so extremely?

I basically added the following to the info.plist file.

<key>NSAllowsArbitraryLoads</key>
<true/> 

Like this:

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

See more info on this in the link in @while1's answer above.



回答3:

your code looks familiar to me seems you're learning Build apps with react native course offered by Stephen Grider.

Even i had this issue.

include delete GLOBAL.XMLHttpRequest; at the beginning of api.js file.

Like this:

delete GLOBAL.XMLHttpRequest;
var _ = require('lodash');
var rootUrl = 'http://api.openweathermap.org/data/2.5/weather?APPID=xxxxxxxxxxxxxxxxxxxxxx';