我正在开发一个从外部API中获取数据的应用程序.每当用户尝试建立连接并且没有连接时,他们就会收到丑陋的红色死亡屏幕. 我一直在玩NetInfo来缓解这个问题,特别是NetInfo.isConnected. 我的
我一直在玩NetInfo来缓解这个问题,特别是NetInfo.isConnected.
我的渲染逻辑的结构方式,我不认为我可以得到this.state.isConnected === false实际触发 – 即使我故意在iOS模拟器中断开互联网.如果我将此逻辑设置为在this.state.isConnected返回任何虚假值时触发其AlertIOS.Alert方法,即使用户有连接,它也会触发该令人不快的警报,因为getInitialState最初将其设置为null.我该怎么办呢?
另外,我是否应该为我的所有组件重新创建这个逻辑,因为我有一种感觉,我需要几乎不断检查网络访问?
===
这是我的getInitialState生命周期方法
getInitialState: function() { return { accessToken: false, isConnected: null, selectedTab: 'products' } },
然后在componentWillMount中,我为NetInfo.isConnected设置了一个事件监听器,并手动获取我的连接状态:
componentWillMount: function() { NetInfo.isConnected.addEventListener('change', this.handleConnectivityChange) NetInfo.isConnected.fetch().done((data) => { console.log(this.state.isConnected); this.setState({ isConnected: data }) }) },
一旦我的componentDidMount,我检查我的isConnected布尔值是否返回true并且我的accessToken不存在.如果两个条件都满足,我会为我的令牌进行API调用:
componentDidMount: function() { if (this.state.isConnected && !this.state.accessToken){ api.getToken() .then((responseData) => { this.setState({ accessToken: responseData.access_token, }); }) .done(); } },
我还处理了对componentWillUnmount的事件监听器的删除:
componentWillUnmount: function() { NetInfo.isConnected.removeEventListener( 'change', this.handleConnectivityChange ); },
我的事件监听器的handleConnectivityChange回调是:
handleConnectivityChange: function(change) { this.setState({ isConnected: change }) console.log("I have changed!" + change) },
最后,我的render方法根据我的连接状态返回三件事之一:
render: function() { if (this.state.isConnected === 'null') { return ( <View style={styles.container}> <Loading loaded={this.state.isConnected} /> </View> ) } if (this.state.isConnected === 'false') { return ( <View> {AlertIOS.alert('You need to be connected to the internet!')} </View> ) } return ( <TabBarIOS> <Icon.TabBarItem title='Home' selected={this.state.selectedTab === 'products'} iconName={'home'} iconSize={20} onPress={() => { if (this.state.selectedTab !== 'products') { this.setState({ selectedTab: 'products' }); } else if (this.state.selectedTab === 'products') { this.refs.productRef.popToTop(); } }}> {this.renderProductView()} </Icon.TabBarItem> <Icon.TabBarItem title="Collections" selected={this.state.selectedTab === 'collections'} iconName={'list'} iconSize={20} onPress={() => { if (this.state.selectedTab !== 'collections') { this.setState({ selectedTab: 'collections' }); } else if (this.state.selectedTab === 'collections') { this.refs.collectionRef.popToTop(); } }}> {this.renderCollectionView()} </Icon.TabBarItem> <Icon.TabBarItem title="About" selected={this.state.selectedTab === 'about'} iconName={'info'} iconSize={20} onPress={() => { this.setState({ selectedTab: 'about' }); }}> {this.renderAboutView()} </Icon.TabBarItem> </TabBarIOS> ) },我最终以下列方式构建我的应用程序:
首先,我在我的异步API调用中添加了一个catch语句.它们看起来像这样:
getCollectionsData: function() { api.getFeaturedCollections(this.props.accessToken) .then((responseData) => { this.setState({ featuredCollectionsDataSource: this.state.featuredCollectionsDataSource.cloneWithRows(responseData.collections), loaded: true }) }) .then(() => { api.getAllCollections(this.props.accessToken) .then((responseData) => { this.setState({ allCollectionsDataSource: this.state.allCollectionsDataSource.cloneWithRows(responseData.collections), }) }) }) .catch((error) => { AlertIOS.alert('Error', 'You need to be connected to the internet') }) .done() },
我还将API调用逻辑移动到它自己的函数中,并在componentWillMount期间调用它.
然后,我为AppState.IOS添加一个更改侦听器,它检查在前台/后台运行的应用程序:
componentDidMount: function() { AppStateIOS.addEventListener('change', this.handleAppStateChange); }, componentWillUnmount: function() { AppStateIOS.removeEventListener('change', this.handleAppStateChange); },
我对这些更改的处理程序只调用getCollectionsData.