ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

React Native SDKを使ってニュースアプリを作る

f:id:mbaasdevrel:20180306160753p:plain

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

f:id:mbaasdevrel:20191125154653p:plain

記事データは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;

f:id:mbaasdevrel:20191125154707p:plain

まとめ

ここまででフィードの一覧表示と詳細表示ができあがりました。さらにお気に入り機能などを追加していきます。コードは下記のリポジトリにあります。実装時の参考にしてください。

NCMBMania/react-native-feed-app: React Native SDKを使ったニュースアプリ実装です

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。