[英]React-native fetch failing to setState when error is thrown
I am trying to handle a bad HTTP response with the fetch()
function in my React Native Component. 我正在尝试使用我的React Native组件中的
fetch()
函数处理错误的HTTP响应。 I have used the code from here which suggests creating a module to handle response errors. 我从这里使用了建议创建一个模块来处理响应错误的代码。
// 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 };
This is the code for my component: 这是我的组件的代码:
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
I have made sure that the test server is currently giving 502 Gateway errors. 我已确保测试服务器当前出现502网关错误。
The behaviour I expect is that when an error is thrown by the line .then(ApiUtils.checkStatus)
it should be caught by the .catch
function and state should be updated by this.setState({load_failed: true});
我期望的行为是,当
.then(ApiUtils.checkStatus)
行引发错误时,应通过.catch
函数捕获该.catch
并应通过this.setState({load_failed: true});
更新状态this.setState({load_failed: true});
. 。 However, I get the error message
ExceptionsManager.js:55 this.setState is not a function
. 但是,我收到错误消息
ExceptionsManager.js:55 this.setState is not a function
。
I find this odd because the following works within the .then( . . .)
function above it: 我觉得这很奇怪,因为以下内容在其上方的
.then( . . .)
函数中起作用:
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData),
loaded: true,
});
Why does the .catch
lambda not have access to this.setState
where the previous function does? 为什么
.catch
lambda无法访问上一个函数所在的this.setState
? Can I use .bind()
somehow? 我可以以某种方式使用
.bind()
吗?
If it is not possible to access this.setState
within the catch
function, how can I change state.load_failed
to true
if I get a poor HTTP response? 如果无法在
catch
函数中访问this.setState
,如果收到较差的HTTP响应,如何将state.load_failed
更改为true
?
I attempted to pass the exception to the calling function and then change the state from the parent function, like so: 我试图将异常传递给调用函数,然后从父函数更改状态,如下所示:
I changed the .catch()
function to this: 我将
.catch()
函数更改为此:
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();
}
and then changed the calling function like so: 然后像这样更改调用函数:
componentDidMount(){
try{
this.fetchData();
}
catch(error){
this.setState({load_failed: true});
}
console.log(this.state.load_failed);
} }
However, I then get a simple ExceptionsManager.js:55 Error
. 但是,然后我得到一个简单的
ExceptionsManager.js:55 Error
。
I tried removing .done()
, but the catch
block fails to handle the exception, state does not change and I get a warning: Possible Unhandled Promise Rejection (id: 0):
. 我尝试删除
.done()
,但是catch
块无法处理该异常,状态没有更改,并且收到警告: Possible Unhandled Promise Rejection (id: 0):
I realise that this may have something to do with async functions in javascript and what the error is passed to, but I'm not 100% sure. 我意识到这可能与javascript中的异步函数以及错误会传递给什么有关,但我不确定100%。
Environment: OSX 10.10, Android 4.1.2, React-native 0.29.2 环境:OSX 10.10,Android 4.1.2,React-native 0.29.2
Your function is not running in the same context ( this
value) as you expect. 您的函数未在您期望的相同上下文(
this
值)中运行。 To solve this, either use an arrow function which keeps the same this
: 为了解决这个问题,请使用箭头功能,保持相同
this
:
.catch(error => {
console.log("Error:" + error.message);
this.setState({load_failed: true});
})
or explicitly bind
to the current this
: 或显式
bind
到当前this
:
.catch(function(error){
console.log("Error:" + error.message);
this.setState({load_failed: true});
}.bind(this))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.