React Native SDKを使ってサンプルアプリを開発してみます。今回はexpoを使って、iPhoneシミュレータで開発を進めていきます。
実装するアプリの動きは次のようになります。
- 起動するとニュースの一覧が表示される
- タイトルをタップすると、記事の詳細が見られる
いわゆるフィードリーダーと同じ仕組みですが、よく使われる機能かと思います。
今回はまず記事一覧を表示する部分を実装します。
利用するライブラリについて
今回はマスター(記事一覧)と詳細(記事本文)に分かれています。そこで、React Native用の下記ライブラリを利用します。
- react-native-gesture-handler
- react-navigation
- react-navigation-stack
NCMB SDKの扱い
SDKはApp.tsxで初期化し、global変数に登録しています。
import config from './config.json'; import NCMB from 'ncmb-react-native'; const ncmb = new NCMB(config.applicationKey, config.clientKey); global.ncmb = ncmb;
App.tsxの編集
App.tsxではタップでの画面遷移をサポートするため、react-navigation-stackとreact-navigationを使います。
import {createStackNavigator} from 'react-navigation-stack'; import {createAppContainer} from 'react-navigation';
そしてHome.tsx(後述)を読み込みます。これは一覧画面を構成します。
import Home from './components/Home';
そして画面にスタックされる要素として登録します。これでナビゲーションが使えるようになります。
const HomeStack = createStackNavigator({ Home: { screen: Home } });
さらにコンテナ化することで、画面遷移処理を追加します。
const HomeContainer = createAppContainer(HomeStack);
最後に画面を作成します。
export default class App extends Component { render() { return ( <HomeContainer /> ); } }
Home.tsxの内容
続いてホーム画面を解説します。ここは画面の大枠、そして記事一覧を作るListコンポーネント(後述)を読み込みます。跡はスタイルシートを使って多少装飾しています。行っている処理は簡単なものなので、下記のコードを見てもらえれば分かるかと思います。
import React, { Component } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import List from './List'; export default class Home extends Component { render() { const {navigation} = this.props; return ( <View style={styles.container}> <Text style={styles.header}>ニュースのヘッダー</Text> <List navigation={navigation} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 60, backgroundColor: '#fff', }, header: { textAlign: 'center', fontWeight: 'bold', fontSize: 25 } });
List.tsxの内容
List.tsxではmBaaSから記事一覧を取得して表示します。まず画面(リスト部)を紹介します。
class List extends Component { constructor() { super(); this.state = { entries: [] } } componentDidMount() { this.fetchData().done(); } async fetchData() { const Entry = global.ncmb.DataStore('Entry'); const entries = await Entry.fetchAll(); this.setState({entries: entries}); } render() { const moveDetail = (item) => { this.props.navigation.navigate('Detail', item); } this.data = []; return ( <View style={styles.container}> <FlatList data={this.state.entries} keyExtractor={(item, index) => item.get('objectId')} renderItem={({item}) => <View> <Text ellipsizeMode='tail' numberOfLines={1} style={styles.title} onPress={() => moveDetail(item)}> {item.get('title')} </Text> <Text style={styles.date_published}>{item.date_published}</Text> <Text ellipsizeMode='tail' numberOfLines={3} style={styles.summary} onPress={() => moveDetail(item)}> {item.get('description')} </Text> </View> } /> </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 22 }, title: { padding: 10, fontSize: 18, height: 44, fontWeight: 'bold' }, date_published: { textAlign: 'right', paddingRight: 20, color: 'grey' }, summary: { padding: 10, fontSize: 18, color: '#333', height: 80, } }); export default List
記事データはNCMBMania/webapi-cache-script: スクリプト機能でWeb APIのレスポンスをキャッシュしますを使って、データストアに保存しています。これを使ってFeed/Entryというクラスにデータを保存しています。
データの取得は次のように行います。
const Entry = global.ncmb.DataStore('Entry'); const entries = await Entry.fetchAll(); this.setState({entries: entries});
Detail.tsxの内容
ここまででデータの取得、そしてタップ時の表示画面(Detail.tsx)は受け取ったデータを表示しているだけです。
import React from 'react'; import { View, StyleSheet, Text, ScrollView } from 'react-native'; import HTMLView from 'react-native-htmlview'; class Detail extends React.Component { render() { const item = this.props.navigation.state.params; return ( <View style={styles.container}> <Text style={styles.title}>{item.get('title')}</Text> <Text style={styles.date_published}>{item.get('pubDate')}</Text> <ScrollView style={styles.scrollView}> <HTMLView stylesheet={styles.body} value={item.get('content')} /> </ScrollView> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, paddingTop: 22 }, title: { padding: 10, height: 88, textAlign: 'center', fontWeight: 'bold', fontSize: 25 }, date_published: { textAlign: 'right', paddingRight: 20, color: 'grey' }, scrollView: { padding: 10, paddingTop: 20, }, body: { fontSize: 100, height: 500, } }); export default Detail;
まとめ
ここまででフィードの一覧表示と詳細表示ができあがりました。さらにお気に入り機能などを追加していきます。コードは下記のリポジトリにあります。実装時の参考にしてください。
NCMBMania/react-native-feed-app: React Native SDKを使ったニュースアプリ実装です