2018年2月18日

プログラミング

APIから値を取得し表示する 【これからはじめるReact Native】

目次

  1. はじめに
  2. データをfetchする
  3. コンポーネントライフサイクル
  4. 実装を行う
  5. まとめ

はじめに

前回は、Expoを使ったReactNativeのアプリ開発についてご紹介しました。

Expoでアプリを作る 【これからはじめるReact Native】

Expoは複雑でカスタマイズしたいようなアプリケーションには向いていませんが、機能が限られているアプリケーションであればとても簡単に開発が可能です。
今回開発するのは、サーバと通信をし、そのデータをリストとして表示するアプリケーションです。

多くのモバイルアプリケーションは、端末上で全てデータを持っているわけではなく、サーバと通信しそのデータを取得し表示するような形となっています。
今回もそういったAPIを使用し、アプリケーション内に取得したデータを表示するものを開発していきます。

データをfetchする

それでは、Expoで新しいプロジェクトを作ります。
App.jsから、APIで値をHTTPリクエストしてみましょう。
こちらのリファレンスにあるように、HTTPリクエストは fetch で行うことができます。
公式リファレンス Networking

POINT!!

fetchでも十分事足りますが、別のHTTPクライアントライブラリが使われることも多いです。特にシンプルな書き方で使えるaxiosというライブラリが人気です。 また、axiosはVue.jsなどでも使われることが多いです。

では、公式サンプルにもある、https://facebook.github.io/react-native/movies.json にGETメソッドでアクセスしてみましょう。
これだけです。
fetch('https://facebook.github.io/react-native/movies.json');
値としてはこれらのものを返してくれます。

{
    title: "The Basics - Networking",
    description: "Your app fetched this from a remote endpoint!",
    movies: [
        {
            title: "Star Wars",
            releaseYear: "1977"
        },
        {
            title: "Back to the Future",
            releaseYear: "1985"
        },
        {
            title: "The Matrix",
            releaseYear: "1999"
        },
        {
            title: "Inception",
            releaseYear: "2010"
        },
        {
            title: "Interstellar",
            releaseYear: "2014"
        }
    ]
}

このmoviesの値をリストとして展開するアプリケーションができそうですね。

では、このfetchメソッドをどこに置くか考えてみましょう。
アプリケーションを立ち上げたタイミングで値を取得してくれたら、その後のリスト展開が上手くいきそうですね。
さて、このタイミングについては、コンポーネントライフサイクルを理解してから実装する必要があります。

コンポーネントライフサイクル

Reactには、コンポーネントライフサイクルと呼ばれるサイクルがあり、そのタイミングで処理を発動することができます。
具体的には「コンポーネントが作成されたタイミング」、「マウント(画面上に表示)されたタイミング」などがあり、公式リファレンスから簡単に列挙していきます。

componentWillMount()

render() 、つまりマウントの前に呼び出されるメソッドです。

componentDidMount()

マウントが終わった後に呼び出されるメソッドです。

componentWillReceiveProps()

新しいpropsを受け取ると呼び出されるメソッドです。

shouldComponentUpdate()

stateやpropsに更新があった際に、マウントの前に呼び出されるメソッドです。

componentWillUpdate()

コンポーネントの更新マウントされる前に呼び出されるメソッドです。

componentDidUpdate()

コンポーネントの更新マウントされた後に呼び出されるメソッドです。

ちょっと一言

componentWill~系のメソッドはReactのVersion16.4でDeprecate (非推奨)となり、今後廃止されていくようです。16.3 and 16.4 releases

POINT!!

普通のJavaScriptやjQueryを触られたことがある方は、window.onload や$(function(){});、$(document).ready(function(){}); などのイベントを見たことがあるかと思いますが、そちらと近いかもしれません。もちろんjQueryなどは実際のDOMを操作するのに対し、Reactのライフサイクルメソッドでは仮想DOMの生成や内部の状態(state)といった要素が関連する点が大きく異なります。

では、今回のケースの場合はどのメソッドを使うべきでしょうか。
アプリケーションを立ち上げたタイミングでfetchが行われ、その後にrender() (描画)される必要がある為、componentWillMount() 内で行うのが良さそうですね。

実装を行う

では、実際にコードを書いていきましょう。
Expoのサンプルコードを極力触らず、元の素材も使いながらシンプルに作っていきます。
出来上がるイメージはこちらです。

App.js

import React, { Component } from 'react';
import { Text, View, ScrollView, StyleSheet } from 'react-native';
import { Constants } from 'expo';

// You can import from local files
import AssetExample from './components/AssetExample';

// or any pure javascript modules available in npm
import { Card } from 'react-native-elements'; // 0.18.5

export default class App extends Component {
  state = { movies: [] };

  componentWillMount() {
    return fetch('https://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => 
        this.setState({ 
          movies: responseJson.movies,
          title:  responseJson.title
        })
      )
      .catch((error) => {
        console.error(error);
      });
  }

  renderMusics() {
    return this.state.movies.map(movie =>
        <AssetExample key={movie.title} movie={movie} />
    );
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.paragraph}>
          {this.state.title}
        </Text>
        <ScrollView>
          <Card title="Local Modules">
            {this.renderMusics()}
          </Card>
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
  },
  paragraph: {
    margin: 24,
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#34495e',
  },
});

AssetExample.js

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

export default class AssetExample extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.paragraph}>
          {this.props.movie.title}
          ({this.props.movie.releaseYear})
        </Text>
        <Image style={styles.logo} source={require("../assets/expo.symbol.white.png")}/>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    justifyContent: 'center',
  },
  paragraph: {
    margin: 24,
    marginTop: 0,
    fontSize: 14,
    fontWeight: 'bold',
    textAlign: 'center',
    color: '#34495e',
  },
  logo: {
    backgroundColor: "#056ecf",
    height: 128,
    width: 128,
  }
});

解説

では、App.jsから見ていきましょう。
まず注意するポイントは、ScrollViewです。
import { Text, View, ScrollView, StyleSheet } from 'react-native';

        <ScrollView>
          <Card title="Local Modules">
            {this.renderMusics()}
          </Card>
        </ScrollView>

ScrollViewですが、こちらはその名前の通りスクロールするViewのコンポーネントです。
こうしたAPIから動的に値を取ってくるものなど、件数が多いとどうしてもViewの場合は表示しきれなくなりがちです。この場合にはスクロールしなければ全体を見ることができず、ScrollViewが必要となります。

そして次のポイントは、fetchで取得した値をstateに保存している処理です。

  componentWillMount() {
    return fetch('https://facebook.github.io/react-native/movies.json')
      .then((response) => response.json())
      .then((responseJson) => 
        this.setState({ 
          movies: responseJson.movies,
          title:  responseJson.title
        })
      )
      .catch((error) => {
        console.error(error);
      });
  }

この処理でAPIの取得に成功した場合に、stateのmovieとtitleに値を設定しています。
moviesは配列形式の為に、最初に state = { movies: [] }; と初期化している点もポイントです。

  renderMusics() {
    return this.state.movies.map(movie =>
        <AssetExample key={movie.title} movie={movie} />
    );
  }
          <Card title="Local Modules">
            {this.renderMusics()}
          </Card>

そして、これらでCardの中身にmoviesをmapし、全件を1つずつAssetExampleコンポーネントとしてレンダリングさせています。
その際にmovieの中身も渡していますね。

では、次にAssetExample.jsです。

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.paragraph}>
          {this.props.movie.title}
          ({this.props.movie.releaseYear})
        </Text>
        <Image style={styles.logo} source={require("../assets/expo.symbol.white.png")}/>
      </View>
    );
  }
}

そして、テキスト部分にpropsに設定したmovieのtitleやreleaseYearを使うことで、APIで取得した値を動的に表示させていることがわかるかと思います。

まとめ

今回はAPIから値を取得し、表示させる処理を実装しました。
またその際にコンポーネントのライフサイクルメソッドも確認しました。
Expoを使っている為、今回実装した内容はすぐにスマホで確認できるはずです。

次回は、レイアウトの整え方などを解説します。

1

0

AUTHOR

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にeishis, Inc.を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

アプリでもっと便利に!気になる記事をチェック!

記事のお気に入り登録やランキングが表示される昨日に対応!毎日の情報収集や調べ物にもっと身近なメディアになりました。

eishisでは一緒に働く仲間を募集しています

正社員や業務委託、アルバイトやインターンなど雇用形態にこだわらず、
ベテランの方から業界未経験の方まで様々なかたのお力をお借りしたいと考えております。

話を聞いてみたい

運営メンバー

eishis

Eishi Saito 総務

SIerやスタートアップ、フリーランスを経て2016年11月にeishis, Inc.を設立。 マーケター・ディレクター・エンジニアなど何でも屋。 COBOLからReactまで色んなことやります。

sasakki デザイナー

アメリカの大学を卒業後、日本、シンガポールでデザイナーとして活動。

しまだ

しまだ デザイナー

WebAR/VRのデザインと3DCG制作がメインです。 肩書きは「アニメ案件に関わりたいデザイナー」。

Miu マーケター

ドイツでWEBマーケティングしています。

しんのき エンジニア

新しい技術が好きなWebエンジニアです。 元々インフラやPHPをやっていたのですが、最近はReact NativeとFirebaseを使って頑張ってます。

yamakawa

やまかわたかし デザイナー

フロントエンドデザイナー。デザイン・HTML/CSSマークアップ・JSアニメーション実装を担当しています。

furuya エンジニア

サーバーサイド、フロントエンド、Unityと色々手を出してる雑食系エンジニア。ReactNativeが最近のマイブーム。

Sayaka Osanai デザイナー

Sketchだいすきプロダクトデザイナー。シンプルだけどちょっとかわいいデザインが得意。 好きな食べものは生ハムとお寿司とカレーです。

はらた

はらた エンジニア

サーバーサイドエンジニア Ruby on Railsを使った開発を行なっています

うえまつゆい エンジニア

サーバーサイドエンジニアからフロントエンドエンジニアになりました。主にReact Nativeでのアプリ開発をしています。

CONTACT PAGE TOP