ここまでの記事で作ってきたニュースアプリに、今回はAPIで記事を取得するまでの間、ロード中であることが分かるようローディングマークを表示させる方法を紹介する。
ここまでの記事
ActivityIndicator
React Nativeには、ローディング中であることをユーザーに知らせるための専用APIとして「ActivityIndicator」というものが用意されている。
使い方
まずはAPIのインポート。
import { ActivityIndicator } from 'react-native';
次にロード中か、そうでないかを判断するためのstate変数を用意する。
ここまで作ってきたApp.jsのコンストラクタにisLoadingというstateを追加しよう。
constructor() {
super();
this.state = {
isLoading: true,
threads: [],
}
}
ロード中の場合はtrue、ロードが完了した場合はfalseを返すものとして、初期値をtrueに設定しておく。
state変数の用意が出来たら、通信が完了した時点でstateを書き換えるよう、componentDidMount内のコードも修正する。
componentDidMount() {
fetch("https://www.reddit.com/r/newsokur/hot.json")
.then((response) => response.json())
.then((responseJson) => {
let threads = responseJson.data.children;
threads = threads.map(i => {
i.key = i.data.url;
return i;
});
this.setState({threads: threads, isLoading: false});
})
.catch((error) => {
console.error(error);
})
}
次にisLoadingの値によって処理を分ける条件分岐を書いていく。
JSXで条件分岐を行う場合は三項演算子を使う必要がある。
{ isLoading ? <ActivityIndicator /> : /*通常処理*/ }
ここまでをApp.jsに反映させると次のようになる。
import React, { Component } from 'react';
import {
Text, View, FlatList, Image, Dimensions, ActivityIndicator
} from 'react-native';
export default class App extends Component {
constructor() {
super();
this.state = {
isLoading: true,
threads: [],
}
}
componentDidMount() {
fetch("https://www.reddit.com/r/newsokur/hot.json")
.then((response) => response.json())
.then((responseJson) => {
let threads = responseJson.data.children;
threads = threads.map(i => {
i.key = i.data.url;
return i;
});
this.setState({threads: threads, isLoading: false});
})
.catch((error) => {
console.error(error);
})
}
render() {
const { threads, isLoading } = this.state;
const { width } = Dimensions.get('window');
return(
<View style={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
{isLoading ? <ActivityIndicator /> :
<FlatList
data={threads}
renderItem={({item}) => {
return(
<View style={{
flex: 1,
flexDirection: 'row',
width: '100%'
}}>
<Image
style={{
width: 50,
height: 50
}}
source={item.data.thumbnail}
/>
<View style={{
flex: 1,
flexDirection: 'column'
}}>
<Text>{item.data.title}</Text>
<Text style={{color: '#ababab', fontSize: 10}}>{item.data.domain}</Text>
</View>
</View>
)
}}
/>
}
</View>
)
}
}
expo startコマンドでアプリを実行すると、以下のようなローディングマークがしばらく表示された後に記事リストが表示される。