#reactnative
#アプリ開発
#チュートリアル
#Expo
#入門

【両OS対応】 React Nativeで爆速モックアップ/プロトタイプアプリを作ろう 1/3 【ウェルカム画面編】

note.muの中の方からもコメント頂けました!ありがとうございます!

↑このシリーズの最終完成形

ezgif.com-video-to-gif (9).gif

↑この記事での目標

この記事で得れる物

・上図のスマホアプリが作れるようになる
・React Nativeの流れを図で直感的にわかる
・なぜこのようにプログラミングをしたのかまでわかる

この記事の対象者

  • アプリ開発経験そんなない方
  • Web系開発経験そんなない方
  • でもまあほんのちょっとプログラミングかじった事ある方(かじるどころかなめた程度の方でもOKです!)

大丈夫です、僕も当時こんな感じでした。Swift(iOS用プログラミング言語)もKotlin(Android用プログラミング言語)も知らなければ、よく聞くjQueryすら触った事ないほどJavaScript(Web系プログラミング言語)に対する知識もカスでした泣。それでも習得できたので大丈夫です。筆者が水先案内人として読者の方々を、「後は自分でググればいける」というレベルまで引き上げます。また、Windowsでも開発できますが、本記事ではMacで作る事を想定してます。

React Nativeとは?

本来ならiOSアプリとAndroidアプリは別言語で書かなければいけなかったのですが、2015年くらいにiOSとAndroidの両アプリを同時に書けちゃう画期的なプログラミング言語をFacebook社が開発しました。それがReact Nativeです(正確にはReact Nativeはプログラミング言語ではなくて、実際はJavaScriptって言語で書きます)。

処理速度も速く、高く評価されており、FacebookやInstagramは元よりAirbnbなどの超有名アプリもReact Nativeにどんどん乗り換えています。日本製アプリで言うとメルカリProgateもReact Nativeだそうです。理由は一言で言うと、開発スピードが速いからです。トレンドの移り変わりが激しい現代のITベンチャーにおいてこれほど嬉しい利点は他にないでしょう。

この記事の目的は?

……と、つまり激アツなプログラミング言語なのですがいかんせん日本語のまとまった情報が少なく、僕が学ぶ際に非常に苦労したのでこのチュートリアル記事を執筆することにしました。

「起業したい!良いアイデアを思いついた!でもアプリ作ったことないし、だからといって周りにエンジニアもいない……よしここは一丁自分でプロトタイプを作ってみよう。Instagram立ち上げた人もメルカリの創業者も最初はプログラミング未経験から始めたんだし!」
……と意気込んで調べてみるものの、出てくるQiitaなどの記事はどれも既にある程度の知識を持ってる前提で話が進んでることがしばしば。いやソースコードだけ貼られてもわかんねえし、みたいな。

そこでこのReact Nativeを初学者でも簡単に学べれるようになれば、iOS/Androidの両アプリを一気に作れちゃうし、超速攻で手元にある実機で動作確認できるし、リリース後はApp Storeの審査を待たずに細かな修正をできるし……と言ったベンチャーにとって非常に有利になる武器を持った状態からスタートできます。そして将来性ありまくりな言語であることは間違いなく、何より僕自身「アプリってこんな簡単に作れるんだ!」と感動したのでその感動をもっと広めたく執筆しました。

SwiftもKotlinもJavaScriptも知らなかった筆者がReact Native(≒JavaScript)を学ぶ際に実際に引っかかった点を主に、「もっとこうやって教えてくれたらいいのに」という視点から超初心者(かつての自分)向けにスクショ豊富で書いてます。わかりやすさを優先しているためざっくりとした説明が多く、本当の意味での正確性には欠けているかもしれません。ただ読み進めてコード書き写してくだけでそれなりのアプリが作れるようになる、そんな記事にしたいと思います。実際にあなたのスマホ上で作ったアプリを動かしますので、スマホからではなくPCからの閲覧推奨です。

作るアプリは"旅行記アプリ"です。過去に自分が行った国と日付を入力し、その時の思い出の写真とその旅行の3段階評価を付けて保存していく、というアプリです(Trip + record = Treco …のつもり)。まあ使い道があるかどうかはいいとして(笑)、このアプリにはよくある要素の

  • 真ん中が + プラスボタンになってるタブ構成 & 画面遷移
  • 日付等を選ぶプルダウンメニュー
  • 地図や画像の配置
  • レビューの中から良い / 普通 / 悪いを仕分けする方法

などが多く積み込まれており、かつ完成後に自分で色々操作してニヤニヤできる(コレ重要)という事で選びました。あとはこれらの基礎要素を応用して組み替えたりしていけば、大体頭の中で想像しているアプリを実装できるようになりますし、何よりこのチュートリアルシリーズを読み終わってる頃には、自力で検索して必要な情報だけを探せれるようになっています。

本記事では以上のような旅行記アプリの、初回起動時に現れるウェルカム画面までを実装するチュートリアルです。このチュートリアルシリーズの各記事の反響が良ければ続きも執筆します ;->

1. ウェルカム画面編 ← 今ココ
2. ホーム画面編
3. プラスボタン編

開発環境を整えよう

手始めとしてMacでiOSアプリを開発することを想定して開発環境を構築します。まずはMacのApp StoreからXcodeをダウンロードします。容量大きいんで結構時間かかります。

Screen Shot 2018-04-29 at 01.25.25.png

Xcodeのインストールが終わったら、少しXcodeの設定を確認します。画面左上のメニューからXcodePreferencesに行き、

2.jpg

LocationsタブのCommand Line Toolsで一番最新のバージョンのやつを選択して下さい。

3.jpg

次にReact Nativeを開発するための下準備をしましょう。と言っても下準備に必要なもの達をインストールするためには、先にHomebrewというやつをインストールしなければいけません…。Macからターミナルを開くと

4.png

5.jpg

自分のMacの名前の横にドルマーク$があって、ドルマーク$の右側から文字が入力できるようになります。そこの領域に、

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

上記のドルマーク$以降(/usr/bin/ruby~~の部分)をコピペしてエンターを押すと、何やら聞かれるので再度エンターを押して待ちます。Macのパスワード入力を求められたら素直にパスワードを入力して下さい、怪しいもんじゃありません笑。

上記のHomebrewのインストールが終わったら$ brewコマンドが使えるようになるので、その$ brewを使ってReact Nativeの下準備をします。

$ brew install node

もちろんここでもドルマーク$以降(brew~~の部分)だけをコピペしてエンター。上記が終わったら、

$ npm install npm@latest -g

をして下さい(これは$ npm自身を最新ver. にアプデするコマンドです)。最後に、

$ brew install watchman

をして、下準備は完了です。そしたらいよいよ、最強のReact Native開発ツールであるExpo XDEをこちらからダウンロードします。ダウンロードを待っている間に、こちらでExpoアカウントを作っておきましょう。このアカウントが無いとExpo XDEが使えません泣。

6.png

最後に実際にソースコードを書くエディターソフトですが、極端な話メモ帳ソフトでも何でも良いですが、僕はAtomを強くお勧めします。皆Atoma使ってます、本当です。こちらからダウンロードしましょう

7.png

はい、お疲れ様でした。ここまででや〜っと環境構築が終わりました笑。

実際にアプリを作ってみよう

さあ、ではここから実際にプログラミングを始めましょう。Expo XDEを起動し、つい先ほど作成したアカウントでログインして下さい。

Screen Shot 2018-04-29 at 09.49.15.png

プロジェクトの新規作成で、

9.png

Blankタイプを選び、好きなプロジェクト名を入力します。
(ここではract-native-bakusoku)

10.png

数分待つと…

11.png

なにやら赤いメッセージも出てますが、全然大丈夫です。Atomで先ほど保存したプロジェクトreact-native-bakusokuを早速開きましょう。

12.png

13.png

そして既に勝手にいくつかのファイルが自動で作られており、その中のApp.jsの中身をのぞいてみます。

14.png

なにやらもう既に色々書かれてますね……。ここがExpo XDEの便利な点で、私達の代わりに上記のようなプログラミング雛形を勝手に作ってくれます。ここでTextタグ

App.js
<Text> ~~ </Text>

に囲まれた部分の文章を変えてみましょう。

App.js
<Text>Open up App.js to start working on your app!</Text>

        

<Text>Hello React Native!</Text>

ちなみに、<〇〇>と</〇〇>をセットで〇〇タグと呼びます。
<〇〇>で開けて</〇〇>で閉じるまで、ずっと〇〇の効果が適用されます。

<〇〇>←ここから〇〇の効果が始まり 〜 〇〇の効果はここまで→</〇〇>

んでTextタグは「タグ内の文書をアプリ画面に映し出す」という効果を持っているので、

App.js
<Text>Hello React Native!</Text>

と書けばアプリ画面に"Hello React Native!"って出る、ということです。ではApp.jsを保存して(command⌘+sでも保存できます)、早速アプリを起動して試してみましょう。AtomからExpo EDXに戻って、

15.png

DeviceOpen in iOS Simulatorをクリック。

16.png

するとiOSシミュレータが起動します(結構時間かかります)。このiOSシミュレータを使いたいがために最初にXcodeをインストールしたのです笑。

17.png
画像引用元

初回は恐らく上図のように聞かれるのでOpenをクリック。

18.png

19.png

iOSシミュレータ側のExpo(上図右側のExpo XDEとはまた別物)が起動してから更に待つこと数十秒……

20.png

無事アプリが起動しました!ちゃんとTextタグの変更が反映されてます!

もしここでiPhone Xのシミュレータが起動しちゃった人は、iPhone 8に変更することもできます(本記事では以降iPhone 8でやっていきます)。

21.png

SimulatorHardwareDeviceiOS 〇〇.〇iPhone 8をクリック。すると、iPhone X(一台目)とiPhone 8(二台目)の二つのシミュレータが同時に動いている状態になり、その状態でiOSシミュレータを閉じます(command⌘+qでも閉じれます)。

22.png

iOSシミュレータが二つとも一気に閉じられるので、そしたら再度Expo XDEにてDeviceOpen in iOS Simulatorをクリックすると今度は最初からiPhone 8シミュレータが起動します!

どうやらExpo XDEは最後に起動されたiOSシミュレータを次回も最初に開くので、逆にiPhone Xシミュレータに戻したくなった時は今の手順とは逆に、「iPhone 8の後にiPhone Xを開く」→「2つとも同時に閉じる」→「再度Expo XDEからiOSシミュレータを起動する」でOKです。

JavaScriptの文法エラーチェック機能を追加しよう

さて、ここからアプリをガンガン作って行くのですがその前に、今後ずっとスーパー役に立つ文法エラーチェック機能を追加しておきましょう。この機能を追加する事でエラーを起こす回数がグッと減ります。

Atomを起動してAtomPreferencesとクリックし、

22-1.png

画面左側のInstallタブへ行ってそこでlinter-eslintと検索して下さい。

22-2.png

検索して出てきたlinter-eslint(ロケットアイコン)とlinter(ピカチュウアイコン)の両方をインストールします。

22-3.png

もし先にlinter-eslintを先にインストールすると、「linter-eslintlinterも必要としますけど、そっちも入れて良いっスカ?」って言う青いメッセージが出てきます。まあ、青い方のYes選んでもピカチュウアイコンの方のInstall押しても一緒なんでどちらでも大丈夫です。

そしたら今度はターミナルを起動しreact-native-bakusokuのあるフォルダまで$ cdコマンドで移動します。

$ cd ~/先ほど/Expo XDEで/指定した保存場所/react-native-bakusoku

そこで、

$ ls

と打つと今どんなファイルが存在してるか見れるのですが、恐らく大体こんな感じになってるかと思います。

29.png

そこで下記の$ npmコマンドを実行します。

$ npm install --save-dev eslint-config-rallycoding

何やらダウンロードが始まります。終わったら念のため再度、

$ npm install

を実行して下さい。今度は--save-dev eslint-config-rallycodingは要りません。

最後にreact-native-bakusokuフォルダ内に一個新しく設定ファイルを追加しましょう。Atomからreact-native-bakusokuを右クリック → New Fileを選択し、

22-4.png

.eslintrcというファイル名を付けます。先頭にドット.を付け忘れないで下さい。

22-5.png

そしてその.eslintrcに下記をコピペします↓。

{
  "extends": "rallycoding",
  "rules": {
    "arrow-body-style": 0
  }
}

22-6.png

はい、今度こそ本当の意味で環境構築が終わりました笑。

横スクロールのスライドページを作ってみよう

ではここからどんどん作り込んでいきましょう!アプリ初回起動時に「このアプリの使い方」的な感じでよく出てくる、横スクロール3ページ分くらいのウェルカムページ(正式な名前わからない泣)を手始めに作ってみましょう。この記事の冒頭にもありましたGIFが完成図です↓。

ezgif.com-video-to-gif (9).gif

ヌルッとした感じで左右にスクロールでき、各ページにはステップ別の指示が書いてあり、最後のページには「さあ、始めよう!」なんて書かれたボタンが配置されてるアレです。

早速Atomに戻り、App.jsにブァーってコードを書き始めるのかと思いきや、新しく別のファイルを作ってそこに書きます。どの言語でもそうですがプログラミングは一箇所に全部書くとごちゃごちゃになるし、どっからどこまでが同一機能なのかわかりづらくなるため、各機能ごとに独立して新たなファイルに書きます。んでそれら各ファイルを最後に一箇所のApp.jsに集約するっていう流れです。そうすることによって「A機能を修正したい!」となったらA.jsってファイルだけ弄ればいいし、「B機能がぶっ壊れた!」となればB.jsってファイルだけ直せばよくなります(基本的に)。

ということで、一旦screensというフォルダを作って、その中に新規ファイルWelcomeScreen.jsを新たに作りましょう!

2.gif

App.jsには雛形を勝手に作ってくれたExpo XDEですが、私達が新規に作ったファイルには雛形を自動では書いてくれません。なので真っ新なWelcomeScreen.jsにReact Nativeの以下の雛形を自分達で書いていきます。

WelcomeScreen.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';


class WelcomeScreen extends React.Component {
 render() {
   return (

   );
 }
}


export default WelcomeScreen;

まずはおまじないだと思って、↑上記を(コピペではなくキーボードで)書き写してください。

解説をすると、

WelcomeScreen.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

はReact Nativeを使用するために絶対必要で、これ書かないと始まりません。

WelcomeScreen.js
class WelcomeScreen extends React.Component {

}

上記はWelcomeScreenという名のコンポーネントを作りますよ、という意味です。コンポーネントとは、一つのまとまった機能を表す部品みたいなもので、上述の通り基本的に1機能1ファイルなので1ファイル1コンポーネントとなります。

WelcomeScreen.js
class WelcomeScreen extends React.Component {
 render() {
   return (

   );
 }
}

んでコンポーネントは必ずrender()という名の関数を持っており、そのrender()関数が返すreturn ();の中身がアプリ画面上に描画されます。関数とは、何か入れると中でゴニョゴニョ加工されて姿形を変えて何かしらが返ってくるモノのことを言います。100円玉入れると→中でなんか処理されて→ジュースがボトンッて出てくる自販機と理屈は一緒です笑。入力が入る→中で処理される→出力が返ってくるの3ステップです。コンポーネントはまず最初に(和訳すると"描画する"という意味の)render()関数を実行し、→中でなんか処理したりしなかったりして、→return ();の中に書かれたことが返ってくる→アプリ画面上に描画される……という流れです。つまりrender()の中のreturn ();内に書く内容にほぼ全てがかかってます。

※ちなみにrender()の括弧前にスペースは無いのに、return ();のカッコ前にスペースが1つ有るのは、それで合ってます。ご心配なく。

WelcomeScreen.js
export default WelcomeScreen;

最後のこの一文は、後にこのWelcomeScreenコンポーネントをApp.jsに集約させるときに必要な文章です。App.jsから外部ファイル(≒外部コンポーネント)を取り入れることをインポートすると言いますが、そのためにはWelcomeScreenエクスポートする(取り出す)ことを許可しなければいけません。こういうとこいちいち書かないとすぐエラーなっちゃうのがプログラミング言語の頭固いとこですね汗。

それでは早速重要なreturn ();の中身を書いていきます。React Nativeは便利なもので、スクロール機能を実現するためのScrollViewタグ(SVが大文字なので注意)というものが既に用意されており、我々はその使い方に従って書けばいいだけで、自前で一から作成する必要はありません。

WelcomeScreen.js
class WelcomeScreen extends React.Component {
  render() {
    return (
      <ScrollView>
      </ScrollView>
    );
  }
}

<〇〇>で開いたタグはちゃんと</〇〇>で閉じるのを忘れないでください!それからScrollViewタグ自体もWelcomeScreen.jsにとって外部であるreact-nativeからインポートしておかなければ、エラーなってしまいます。

WelcomeScreen.js
import { StyleSheet, Text, View, ScrollView } from 'react-native';

なので↑上記のように中括弧{ }の中にScrollViewを追加して下さい(SVが大文字なので注意)。

この状態で既に縦スクロールできる状態になってますが、このままでは希望の動作から大分遠いので、

  • horizontal…スクロール方向を横にする
  • pagingEnabled…ヌルッ→ピタって感じで1ページごと止まるようにする
  • flex: 1…描画エリアをスマホ画面上一杯を占有するようにする

の3オプションをScrollViewタグに追加します。こういった追加オプションは下記↓のように開始タグの中に書くことによって反映され、一応プロパティって名前が付いてます。

WelcomeScreen.js
<ScrollView
  horizontal           // horizontal={true}でも可
  pagingEnabled        // pagingEnabled={true}でも可
  style={{ flex: 1 }}
>
</ScrollView>

ここで疑問となるのが、なぜ中括弧{ }が一重の時と二重の時があるのかということですね。まず一重にしろ二重にしろ、一番外側の中括弧{ }は、「今からこの中括弧の中にJavaScriptを書きますよ〜」という合図です。

ん、待てよ…ってことは<〇〇>タグとかはJavaScriptじゃないの…?

正解です笑。ここがまたReact Nativeをややこしくする点なんですけど、React NativeはJavaScriptだけでなくHTML風のやつ(正式名称はJSX)も書けるというルールなんです。そしてボタンの配置位置とかは全てこのHTML風のやつ、つまり<〇〇>タグを使って記述します。しかしそのHTML風のやつの中に更にまたJavaScript書きたくなる時があって(ややこしい汗)、その時は中括弧{ }で囲ってからJavaScriptを書く、というルールです。

23.png

じゃあ二重の中括弧{ }はどうなっているかと言うと、HTML風のやつにとって中括弧{ }は「今からこの中括弧の中にJavaScriptを書きますよ〜」という合図でしたが、JavaScriptにとって中括弧{ }はまた別の意味を指します。それは、JavaScript オブジェクトというものです。まあ名前なんてどうでもいいんですが、{ flex: 1 }を例にすると、

flexという項目の値が → 1である」

という意味の塊となります。これを応用すると{ aaa: 1, bbb: 2, ccc: 3 }は、

aaaという項目の値が → 1である」
bbbという項目の値が → 2である」
cccという項目の値が → 3である」

という3つの情報が一塊りとなった物と言えます。

んで、話を戻してflexという項目はどういう意味かというと、一言で言うと「画面占有エリアの比率」です。今は恩恵をあまり受けてないのでわかりづらいですが、とりあえず{ flex: 1 }はスマホ画面一杯を占有するって意味なんだなと覚えていただければ大丈夫です。

さてこれで横スクロール型の部品が完成したのですが、いかんせん表示する内容をまだ書いていないのでスマホ画面上には何にも表示されません。なのでScrollViewタグ内(との間)に表示したい内容を書いていくのですが、その場にベタ書きしちゃうとこれまたゴチャゴチャになってしまうので、ここは一旦新たな関数renderSlides()render()の直上に作成することにします。

WelcomeScreen.js
class WelcomeScreen extends React.Component {
  renderSlides() {

  }

  render() {
    return (
      <ScrollView
        horizontal
        pagingEnabled
        style={{ flex: 1 }}
      >
        {this.renderSlides()}
      </ScrollView>
    );
  }
}

んで、新しく作ったrenderSlides()関数内に細かな挙動を書いていく、という算段です。render()関数からするとrenderSlides()関数は最早render()の中にあるものではなくなるので、this.renderSlides()のように先頭にthis.を付けて呼び出さなければいけません。この場合thisは「WelcomeScreen」の事を指し、ドット.は、「〜の中の」という意味を指します。render()の中にはないけど、同じWelcomScreenというコンポーネントの中という意味では一緒だから、this.(≒WelcomScreenコンポーネントの中の)を付けることによって呼び出せるようになります。同じ部屋にはいないけど同じ屋根の下で一緒に暮らしてるよね、的な感じです。

ではrenderSlides()関数の中身を書いていきましょう。今回の横スクロールは似たような内容を3ページ分表示させたいので、配列というテクニックを用いて似たような物を3個作りましょう。配列というのは複数の似た者同士を一つにまとめたもので、そうすることによってプログラム上で色々便利なことができます。複数のものをひとまとめにすると言った意味では先ほどのJavaScript オブジェクトと似ていますがちょっと違います。配列は属性の同じ物達をひとまとめにするのに対し、JavaScriptオブジェクトは属性の違う物達をひとまとめにします。例えば、

[ 会員番号001, 会員番号002, 会員番号003, 会員番号004, ... ]

は配列が適していますが、

{ 会員番号: 001, 年齢: 23, 加入年: 2018 }

はオブジェクトの方が向いています。

そして今回は似たようなスライドページを3ページ作るので、配列の方が適しています。配列は上述の通り大括弧[ ]で表現します。下記↓のようにimport文とclass定義文の間に書きましょう。あ、const変数の初回登場時に必ず書かなければいけない魔法の接頭辞です。

WelcomeScreen.js
import React from 'react';
import { StyleSheet, Text, View, ScrollView } from 'react-native';


const SLIDE_DATA = [
  { title: 'Step: 1', text: 'aaa' },
  { title: 'Step: 2', text: 'bbb' },
  { title: 'Step: 3', text: 'ccc' },
];


class WelcomeScreen extends React.Component {
  renderSlides() {

  }

  render() {
    return (
      <ScrollView
        horizontal
        pagingEnabled
        style={{ flex: 1 }}
      >
        {this.renderSlides()}
      </ScrollView>
    );
  }
}


export default WelcomeScreen;

今回は{ タイトル, テキスト }という2種類の属性を持ったオブジェクトを3つ、配列にぶち込んでます。またimport文とclass定義文の間、つまりWelcomeScreenコンポーネントの外に書いたことによって、WelcomScreen内のどの関数からも配列SLIDE_DATAの内容にアクセスできるようになります。

んで配列の何が良いかっていうと、繰り返し処理を超簡単に書けるんですよね。何万回も同じ計算を人間と違ってコンピュータは飽きずに一瞬でやってくれるって、まさにこの配列の恩恵なんですよね。それをやってくれるのが、JavaScriptに最初から備わっているmap()関数です↓。

WelcomeScreen.js
const SLIDE_DATA = [
  { title: 'Step: 1', text: 'aaa' },
  { title: 'Step: 2', text: 'bbb' },
  { title: 'Step: 3', text: 'ccc' },
];


class WelcomeScreen extends React.Component {
  renderSlides() {
    return SLIDE_DATA.map();
  }

配列名.map()と書くと、その配列の中身を一個ずつ細切れにして各要素全てに繰り返し同じ処理をしてくれるという優れものです。そのmap()関数の中に、配列の各要素一個に対してどんな処理をするか細かく書いていきます。ここで出てくるのがアロー関数です。

React Nativeはバンバン新しい概念が出てきますね…(ノд-。)グスン

アロー関数とは、

( 入力 ) => {

  // ゴニョゴニョ…色々な処理があったりなかったり

  return ( 出力 );
}

のように名前すら付いてない関数のことです(厳密には無名関数と完全一緒ではないですが、本記事ではこれ以上立ち入りませんので気にしなくてOKです)。=>の部分が矢印みたいだからアロー関数って呼ぶんですね。

WelcomeScreen.js
const SLIDE_DATA = [
  { title: 'Step: 1', text: 'aaa' },
  { title: 'Step: 2', text: 'bbb' },
  { title: 'Step: 3', text: 'ccc' },
];


class WelcomeScreen extends React.Component {
  renderSlides() {
    return SLIDE_DATA.map(( map関数からの入力達 ) => {
      return ( 水色のページを出力 );
    });
  }

今回は、map()関数から受け取った配列の一要素を入力とし → 水色のページを出力として返す、というアロー関数を書きます。

WelcomeScreen.js
const SLIDE_DATA = [
  { title: 'Step: 1', text: 'aaa' },
  { title: 'Step: 2', text: 'bbb' },
  { title: 'Step: 3', text: 'ccc' },
];


class WelcomeScreen extends React.Component {
  renderSlides() {
    return SLIDE_DATA.map((slide, index) => {
      return (
        <View>
          <Text>{slide.title}</Text>
          <Text>{slide.text}</Text>
          <Text>{index + 1} / 3</Text>
        </View>
      );
    });
  }

まずmap()関数からの入力は主に2つあります。

  1. 配列の各要素の一つ…slide
  2. 現要素の番号…index

つまり今回の場合、

24.jpg

ということになります(プログラミングの世界では先頭番号は1番目ではなくて0番目なので注意)。

そして出力の方は、ドット.(「〜の中の」という意味)を利用して

  • {slide.title}
  • {slide.text}
  • {index + 1} / 3 ... indexには常にプラス1しないと例えば先頭ページが3分の0ページ目になっちゃう汗

の3文書をTextタグを用いて出力しています。しかしここでReact Native特有のルールで、「return ()文はたった一つのタグしか返せない」というものがあります。したがって3つもあるTextタグ達は一つの大きなViewタグで包み込んであげなければいけません。Viewタグは包み込んだタグ達の背景というか下地になるので、例えば背景色を一気に変えたりとかできます(もしHTMLやった事ある方なら、divタグに似てると思ってもらって構いません)。なので早速今回の例に従って背景を水色に変えましょう↓。

WelcomeScreen.js
class WelcomeScreen extends React.Component {
  renderSlides() {
    return SLIDE_DATA.map((slide, index) => {
      return (
        <View
          key={index}
          style={{ flex: 1, backgroundColor: 'skyblue' }}
        >
          <Text>{slide.title}</Text>
          <Text>{slide.text}</Text>
          <Text>{index + 1} / 3</Text>
        </View>
      );
    });
  }

背景色はbackgroundColor: '〇〇'で変えれます(Cは大文字です!)。変更可能な色一覧はこちら。そしてflex: 1は「スマホ画面一杯に」という意味です(覚えてましたか?^^)。

また、style プロパティの上にあるkey プロパティは特に見た目や動作に影響を与えませんが、必要なものです(これ怠ると黄色い警告メッセージが出ます…)。map()関数のように何回も同じ処理をreturnする場合には、returnするパーツ(今回で言うViewタグ)に一意の識別番号をkeyプロパティで付けなきゃいけないというルールがあります。別に文字でも数字でも毎回変わる物なら何でも良いですが、配列のindexは毎回必ず違くなる数字なので、そのままkeyプロパティに使わせて貰います。

ここいらで一旦シミュレータで動作確認してみましょう。そのためには、今書いていたWelcomeScreen.jsを最初の大元であるApp.jsに組み込まなければいけません。まずApp.jsに戻って、先程のWelcomeScreen.jsをimportし、TextタグをWelcomeScreenタグに置き換えます↓。

App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

import WelcomeScreen from './screens/WelcomeScreen';


export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <WelcomeScreen />
      </View>
    );
  }
}


const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

上記↑はWelcomeScreen.jsではなくApp.jsですよ!お間違えなく!

それではExpo XDEに戻り、DeviceOpen in iOS SimulatorをクリックしてiOSシミュレータを起動してみて下さい。もし既に起動済みの方は、ソースコードを保存したそばから変更が反映されているはずです。もし変更が反映されていないようだったら、command⌘+rで更新してみて下さい。

3.gif

って、あれれ〜…

25.jpg

これは配列の各要素slide(map関数からの入力)の幅が適切でないからです。現状幅は何も指定されていないので、Textタグの内容が全部入るだけの幅しかありません。

ここでslideの幅を、スマホ画面の横幅と同じ値に設定します。スマホの画面サイズ情報を入手するために、react-nativeからDimensionsをimportします。

WelcomeScreen.js
import React from 'react';
import { StyleSheet, Text, View, ScrollView, Dimensions } from 'react-native';


const SCREEN_WIDTH = Dimensions.get('window').width;
const SLIDE_DATA = [
  { title: 'Step: 1', text: 'aaa' },
  { title: 'Step: 2', text: 'bbb' },
  { title: 'Step: 3', text: 'ccc' },
];

そしてDimensions.get('window').widthと書けばスマホ画面の横サイズ、Dimensions.get('window').heightと書けばスマホ画面の縦サイズが手に入ります。今回は画面横サイズの情報をSCREEN_WIDTHという名の変数に保存し、

WelcomeScreen.js
import React from 'react';
import { StyleSheet, Text, View, ScrollView, Dimensions } from 'react-native';


const SCREEN_WIDTH = Dimensions.get('window').width;
const SLIDE_DATA = [
  { title: 'Step: 1', text: 'aaa' },
  { title: 'Step: 2', text: 'bbb' },
  { title: 'Step: 3', text: 'ccc' },
];


class WelcomeScreen extends React.Component {
  renderSlides() {
    return SLIDE_DATA.map((slide, index) => {
      return (
        <View
          key={index}
          style={{ flex: 1, backgroundColor: 'skyblue', width: SCREEN_WIDTH }}
        >
          <Text>{slide.title}</Text>
          <Text>{slide.text}</Text>
          <Text>{index + 1} / 3{</Text>
        </View>
      );
    });
  }

アロー関数の中のViewタグのstyle プロパティwidth: SCREEN_WIDTHを追加します。すると、

4.gif

おお〜、大分近づいてきました!ここいらで実機テストしてみましょう!Expoの凄いところは、簡単に即実機テストできちゃうところです。まずはExpo ClientというスマホアプリをApp Store/Google Playからダウンロードして、Expo XDEを起動しているパソコンと同じWiFiに繋いで下さい。

次にExpo XDEShareSend Linkとクリックすると入力したメアドもしくは携帯電話番号(SMS)にリンクが届きます。携帯電話番号の人は、090の最初の0を+81に変えて、090 → +8190 のようにしてください。ハイフンはあってもなくてもどっちでも。

26.png

届いたリンクを押すと先ほどのExpo Clientが立ち上がって……実機でアプリがテストできます!!超簡単!!!このためにExpo使ってると言っても過言ではないほど凄い機能です……。是非実際にマウスではなく指でウェルカムページを左右にスリスリしてみて下さい(笑)

IMAGE ALT TEXT HERE

↑イメージ動画

配置とデザインを整えよう

しかしまだTextタグによる文章が画面左上に固まってるので、良い感じに中央揃えにしてあげましょう。Textタグ達の配置をコントロールするには、背景色の時と同じように、それらを囲んでいるViewタグのstyle プロパティをいじってあげれば良いです。

この続きはnote.muにて

https://note.mu/cube0529/n/n4a130029dfe1

(残り16,854文字 / 画像10枚)

Screen Shot 2018-06-09 at 20.00.40.png