Reagieren-native fetch fehlschlägt, um setState wenn der Fehler geworfen wird

Hintergrund

Ich versuche zu handhaben, ein bad HTTP-Antwort mit der fetch() Funktion in meine Reagieren Nativen Komponente. Ich habe den code von hier, die empfiehlt die Schaffung einer Modul-handle-response-Fehler.

//ApiUtils.js

var ApiUtils = {  
  checkStatus: function(response) {
    if (response.status >= 200 && response.status < 300) {
      return response;
    } else {
      let error = new Error(response.statusText);
      error.response = response;
      throw error;
    }
  }
};
export { ApiUtils as default };

Dies ist der code für meine Komponente:

import React, { Component } from 'react';
import {View, Text, StyleSheet, Slider, ListView} from 'react-native';
import GLOBAL from "../../Globals.js"
import ApiUtils from "../utils/ApiUtils.js"

class FetchedList extends Component {
    constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
          rowHasChanged: (row1, row2) => row1 != row2,
      }),
      loaded: false,
      load_failed: false,
    };
  }
  componentDidMount(){
    this.fetchData();
  }
  fetchData(){
    fetch(GLOBAL.BASE_URL + "/" + this.props.url_section + "/" + String(this.props.weekNo) + "/")
      .then(ApiUtils.checkStatus)
      .then((response) => {
        return response.json()
      })
      .then((responseData) => {
          if(responseData===[] || responseData.length === 0){
            this.setState({
              loaded: false,
              load_failed: true,
            });
          }
          else{
            this.setState({
              dataSource: this.state.dataSource.cloneWithRows(responseData),
              loaded: true,
            });
          }
      })
      .catch(function(error){
        console.log("Error:" + error.message);
        this.setState({load_failed: true});
      })
      .done();
  }
  render() {
    if (!this.state.loaded) {
      if (this.state.load_failed){
        return(
          <View></View>
        );
      }
      return this.renderLoadingView();
    }
    else{
        return (
          <ListView
            dataSource={this.state.dataSource}
            renderRow={this.renderComment}
          /***//>
        );
    }
  }
  renderLoadingView() {
     return (
       <View>
        <Text>Loading . . .</Text>
       </View>
     );
   }

  renderComment(comment){
    return(
      <Text style={styles.row}>{comment.content}</Text>
    )
  }
}

const styles = StyleSheet.create({
  row: {
    //backgroundColor: "antiquewhite",
    flexDirection: "row",
    justifyContent: "flex-start",
    alignItems: "center",
    height: 50
  },
});

module.exports = FetchedList

Habe ich darauf geachtet, dass die test-server ist derzeit mit 502 Gateway Fehler.

Verhalten ich erwarten, ist, dass wenn ein Fehler ausgelöst wird durch die Linie .then(ApiUtils.checkStatus) sollte es sein gefangen durch die .catch Funktion und Status aktualisiert werden sollte, indem this.setState({load_failed: true});. Allerdings bekomme ich die Fehlermeldung ExceptionsManager.js:55 this.setState is not a function.

Ich finde das seltsam, denn die folgenden arbeiten innerhalb der .then( . . .) Funktion oben:

this.setState({
  dataSource: this.state.dataSource.cloneWithRows(responseData),
    loaded: true,
});

Frage

Warum die .catch lambda nicht haben Zugang zu this.setState wo die Vorherige Funktion verrichtet? Kann ich .bind() irgendwie?

Folgen-Auf Die Frage

Wenn es nicht möglich ist, Zugriff auf this.setState innerhalb der catch Funktion, wie kann ich das ändern state.load_failed zu true wenn ich eine schlechte HTTP-Antwort?

Versuchte Behebt

Habe ich versucht, übergeben Sie die Ausnahme an die aufrufende Funktion, und ändern Sie dann den Status aus der übergeordneten Funktion, etwa so:

Änderte ich die .catch() Funktion zu diesem:

fetchData(){
    fetch(GLOBAL.BASE_URL + "/" + this.props.url_section + "/" + String(this.props.weekNo) + "/")
      .then(ApiUtils.checkStatus)
      .then((response) => {
        return response.json()
      })
      .then((responseData) => {
          . . .
      })
      .catch(function(error){
        console.log("Error!");
        throw error;
      })
      .done();
  }

und dann verändert die aufrufende Funktion so auf:

componentDidMount(){
try{
  this.fetchData();
}
catch(error){
  this.setState({load_failed: true});
}
console.log(this.state.load_failed);

}

Aber ich bekomme dann eine einfache ExceptionsManager.js:55 Error.

Ich habe versucht, das entfernen .done(), aber die catch block schlägt fehl, zum behandeln der Ausnahme, Status ändert sich nicht und ich bekomme eine Warnung: Possible Unhandled Promise Rejection (id: 0):. Mir ist klar, dass das möglicherweise etwas zu tun mit dem async-Funktionen in javascript und was der Fehler ist weitergegeben, aber ich bin mir nicht 100% sicher.

Umgebung: OSX 10.10, Android 4.1.2, Reagieren-native 0.29.2

InformationsquelleAutor user3623641 | 2016-09-24
Schreibe einen Kommentar