承接上文《React Native 基础练习指北(一)》,我们来看看React Native如果通过接口获取线上数据并展示。
Tips: 如果使用cmd+R
无法刷新效果,请检查index.ios.js
的权限设置。
一、展示单条数据
通常我们会在require('react-native');
后,写好储存API的变量(此处我们使用简单的API做演示):
var REQUEST_URL = 'http://platform.sina.com.cn/sports_all/client_api?app_key=3571367214&_sport_t_=football&_sport_s_=opta&_sport_a_=teamOrder&type=213&season=2015&format=json';
这里我们暂时使用新浪体育2015年中超联赛信息的接口,可以得到中超16支球队2015赛季的相关信息(未经授权,悄悄的使用,打枪的不要)。
接下来,我们要添加一些初始化的状态,我们可以通过this.state.movies === null
判断数据是否已经成功加载。将下面的代码加在render
方法前面:
getInitialState: function() { return { teams: null,}; },
当react-native
组件加载完成后,我们需要发送我们的请求。React会在react-native
组件加载完成后,使用componentDidMount
方法发送请求,并且只发送一次。
componentDidMount: function() { this.fetchData(); },
下面,我们需要添加fetchData
方法,它是用来取回数据的。在React的工作流程中,setState
会触发一次重绘,随后render
方法会发现this.state.movies
不再是null
,你所需要做的就是使用this.setState({movies: data})
。牢记在最后要使用done()
,否则不会出现错误提示。
fetchData: function() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ teams: responseData.result.data,}); }) .done(); },
现在,我们需要修改render
方法,从而当我们没有拿到数据时,渲染出一个loading
视图,随后呈现出第一个球队信息。
render: function() { if (!this.state.teams) { return this.renderLoadingView(); } var team = this.state.teams[11]; return this.renderTeam(team); },renderLoadingView: function() { return ( <View style={styles.container}> <Text> Loading teams... </Text> </View> ); },renderTeam: function(team) { return ( <View style={styles.container}> <Image source={{uri: team.logo}} style={styles.thumbnail} /> <View style={styles.rightContainer}> <Text style={styles.name}>{team.team_cn}</Text> <Text style={styles.rank}>{team.team_order}</Text> </View> </View> ); }
现在,在iOS模拟器中cmd+R
,在请求拿到返回数据之前,你会看到“Loading teams...”,随后会渲染出第一个球队信息。
二、展示数据列表
下面我们来看看如何把所有数据展示在ListView
组件中,而不是仅仅展示一条数据。
首先我们在最上面定义React
的时候加入ListView
:
var { AppRegistry,Image,ListView,StyleSheet,Text,View } = React;
接下来,我修改render
方法,从而能够以列表方式展示出数据:
render: function() { if (!this.state.loaded) { return this.renderLoadingView(); } return ( <ListView dataSource={this.state.dataSource} renderRow={this.renderscoreboard} style={styles.listView} /> ); },
ListView
可以判断哪些数据发生了改变,并在数据更新时,体现在列表中。
我们不难发现,我们使用了this.state
中的dataSource
。下一步在getInitialState
返回的对象中添加空的dataSource
。随后,我们讲数据存到dataSource
中,我不再使用this.state.movies
来避免数据重复加载,而是使用布尔值this.state.loaded
来判断数据是否成功获取。
getInitialState: function() { return { dataSource: new ListView.DataSource({ rowHasChanged: (row1,row2) => row1 !== row2,}),loaded: false,}; },
下面是完善后的fetchData
方法:
fetchData: function() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.result.data),loaded: true,}); }) .done(); },
最后,我们把ListView
的样式添加到styles
对象中:
listView: { paddingTop: 20,backgroundColor: '#F5FCFF',},