122

I'm getting the following error:

Possible unhandled promise rejection (id:0: Network request failed)

Here's the promise code, I don't see what's wrong here, any ideas?

  return fetch(url)
    .then(function(response){
      return response.json();
    })
    .then(function(json){
      return {
        city: json.name,
        temperature: kelvinToF(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);
    });
}

Edit:

I added a catch function and got a better error:

You passed an undefined or null state object; instead, use forceUpdate(). index.ios.js:64 undefined

Here's the index.ios.js code. The url is fine and giving me the correct json data. I can see with console log that both region.latitude and region.longitude are available in Api(region.latitude, region.longitude). But data is undefined.

I'm still not sure what's going on, why there's a problem with data and why it's undefined.

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

// updated
import React from 'react';

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

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


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

var Weather = React.createClass({
  getInitialState: function() {
    return {
      pin: {
        latitude: 0,
        longitude: 0
      },
      city: '',
      temperature: '',
      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.temperature}</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(data);
        this.setState(data);
      });
  }
});


        

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);
Ruvee
  • 8,611
  • 4
  • 18
  • 44
Agent Zebra
  • 4,410
  • 6
  • 33
  • 66

7 Answers7

87

catch function in your api should either return some data which could be handled by Api call in React class or throw new error which should be caught using a catch function in your React class code. Latter approach should be something like:

return fetch(url)
.then(function(response){
  return response.json();
})
.then(function(json){
  return {
    city: json.name,
    temperature: kelvinToF(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);
 // ADD THIS THROW error
  throw error;
});

Then in your React Class:

Api(region.latitude, region.longitude)
  .then((data) => {
    console.log(data);
    this.setState(data);
  }).catch((error)=>{
     console.log("Api call error");
     alert(error.message);
  });
Harry B
  • 2,864
  • 1
  • 24
  • 44
while1
  • 3,320
  • 19
  • 12
  • 1
    Thank you, I added the catch function in the api also, and it's not throwing an error. Strange. – Agent Zebra Aug 09 '16 at 06:49
  • 2
    Did you added throw error after console.log('There has been a problem with your fetch operation: ' + error.message); in your fetch catch function. See throw error added in first snippet. – while1 Aug 09 '16 at 06:55
  • Ah jeez, missed that, thank you. the error is `Network request failed`, which is the same error I was getting in the beginning. Hmm... still not sure what's going on here. – Agent Zebra Aug 09 '16 at 06:57
  • Any idea why I'm still getting a `Network request failed` error? – Agent Zebra Aug 10 '16 at 01:08
  • 1
    I think problem is in your url request. Not in react naitve any where. Try opening api url in simulator safari to make sure simulator is able to access url. Also make sure your App transport policy allows http call. see http://stackoverflow.com/questions/31254725/transport-security-has-blocked-a-cleartext-http for that. – while1 Aug 10 '16 at 04:24
  • You're right of course, it was the issue in info.plist that you flagged in this question ==> http://stackoverflow.com/questions/38862837/react-native-ios-network-request-failed – Agent Zebra Aug 10 '16 at 19:41
  • What's the difference using `Promise.reject(error`? I tried that but not working, meanwhile `throw error` works fine. – Jeaf Gilbert Mar 03 '21 at 03:48
5

You should add the catch() to the end of the Api call. When your code hits the catch() it doesn't return anything, so data is undefined when you try to use setState() on it. The error message actually tells you this too :)

hasseio
  • 599
  • 2
  • 3
  • Thank you, I added the catch function in the api also, and it's not throwing an error. Strange. – Agent Zebra Aug 09 '16 at 06:50
  • In regards to the network fail error... are you running the fetch inside an emulator? Maybe it can't access the network due to a firewall on your local dev machine? Or maybe the android dns can't resolve the url - so try with an ip address. – hasseio Aug 09 '16 at 23:22
  • Yes running it in the ios simulator, no firewall. How do I try with an ip address? – Agent Zebra Aug 09 '16 at 23:30
  • Edit: sorry just saw the ios requirement... try this answer - http://stackoverflow.com/questions/13542706/iphone-simulator-cannot-connect-to-internet – hasseio Aug 09 '16 at 23:49
3

According to this post, you should enable it in XCode.

  1. Click on your project in the Project Navigator
  2. Open the Info tab
  3. Click on the down arrow left to the "App Transport Security Settings"
  4. Right click on "App Transport Security Settings" and select Add Row
  5. For created row set the key “Allow Arbitrary Loads“, type to boolean and value to YES.

enter image description here

3

Adding here my experience that hopefully might help somebody.

I was experiencing the same issue on Android emulator in Linux with hot reload. The code was correct as per accepted answer and the emulator could reach the internet (I needed a domain name).

Refreshing manually the app made it work. So maybe it has something to do with the hot reloading.

stilllife
  • 1,776
  • 1
  • 18
  • 38
3

In My case, I am running a local Django backend in IP 127.0.0.1:8000 with Expo start. Just make sure you have the server in public domain not hosted locally on your machine. If it is hosted locally find the local IP address like 192.168.0.105 or something and use that

Arun K
  • 868
  • 10
  • 17
  • This was my issue as well. Changed `uri` to something like `uri: "http://192.168.1.64:9001/graphql"` and it started working! Thank you. – Rahul Nov 24 '22 at 19:28
0

For me adding the return error in the catch works, maybe you can give that a try:

.catch(e => {
    console.error(e)
    return e;
})
John Klees
  • 21
  • 3
-5

delete build folder projectfile\android\app\build and run project

Nicola Ben
  • 10,615
  • 8
  • 41
  • 65