アプリ開発といっても、様々な機能を有するアプリが考えられるが、多くのアプリはインターネット接続を前提として作られている。

iOSとAndroidではHTTPリクエストの扱いが大きく異なるが、React Nativeではこれを簡単に扱うためのAPIとして「fetch API」というものが用意されている。

fetchAPIの基本的な使い方

fetchメソッドに対し、メソッドチェーン形式でコールバック関数を記述していく。

fetch("https://www.reddit.com/r/newsokur/hot.json")
	.then((res) => {
		return res;
	})
	.catch((err) => {
		return throw err;
	})

then内のコールバック関数の引数にはリクエストに成功した場合の結果が格納され、catch内コールバック関数の引数にはエラーメッセージが格納される。

JSON形式のレスポンスを受け取る

リクエストの結果がJSON形式の場合、処理を行う前にJSONをパースすることができる。
パースをしないとプレーンテキストとしてデータが取得されるので、オブジェクトや配列として扱う時の処理が大変になる。

fetch("https://www.reddit.com/r/newsokur/hot.json")
	.then((response) => response.json)
	.then((responseJson) => {
		// responseJsonに対する処理
	})
	.catch((err) => {
		return throw err;
	})

fetchAPIを利用してニュースアプリを作る

fetchAPIを利用して、Reddit.comのニュー速R人気記事を取得して表示するだけの簡単なニュースアプリを作ってみる。

まずはコード全文を見てみよう。

import React, { Component } from 'react';
import {
  Text, View, FlatList
} from 'react-native';

export default class App extends Component {
  constructor() {
    super();
    this.state = {
      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});
      })
      .catch((error) => {
        console.error(error);
      })
  }

  render() {
    const { threads } = this.state;

    return(
      <View style={{
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
      }}>
        <FlatList
          data={threads}
          renderItem={({item}) => {
            return(
              <View>
                <Text>{item.data.title}</Text>
              </View>
            )
          }} />
      </View>
    )
  }
}

それではコードについて解説していく。

プロジェクトの作成

今回はExpoを利用して開発を進めていく。

expo initコマンドでプロジェクトを作成する。

expo init redditApi

作成されたプロジェクトのApp.jsにコードを記述していく。

必要なライブラリのインポート

fetchApiは特にライブラリをインポートすることなく使えるので、UI関連のコンポーネントをインポートしていく。

import React, { Component } from 'react';
import {
  Text, View, FlatList
} from 'react-native';

記事データを管理するstateの定義

まず、コンストラクタで記事データを管理するstateを定義する。

constructor() {
  super();
  this.state = {
    threads: []
  }
}

人気記事スレッドを取得する

次に、コンポーネントがマウントされた際にfetchApiを利用して、人気記事を取得する処理を書いていく。

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});
    })
    .catch((error) => {
      console.error(error);
    })
}

注意点としてmap関数でキーを設定する際、単純に連番を付けるとソート処理が遅くなり非推奨とされているので、今回はurlをキーに設定した。

FlatListコンポーネントで記事リストを表示

最後にrenderメソッドでUI表示の処理を書く。

render() {
  const { threads } = this.state;

  return(
    <View style={{
      flex: 1,
      justifyContent: 'center',
      alignItems: 'center',
    }}>
      <FlatList
        data={threads}
        renderItem={({item}) => {
          return(
            <View>
              <Text>{item.data.title}</Text>
            </View>
          )
        }} />
    </View>
  )
}

複数のコンポーネントをリスト形式で表示させる場合はFlatListコンポーネントを使うことが推奨されている。
FlatListの詳しい解説は以下の記事で紹介している。

ここまで出来たら、expo startコマンドでアプリを実行してみる。

今回は単純に記事タイトルだけをリストアップしただけだが、今後の記事でサムネイル画像などを表示させたり、作り込んでいく流れを紹介していこうと思う。