ここまでの記事で作ってきたニュースアプリに、今回は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コマンドでアプリを実行すると、以下のようなローディングマークがしばらく表示された後に記事リストが表示される。

