73
55

More than 5 years have passed since last update.

expoによるReact Nativeのおさらい(最低限)

Posted at

しばらく使ってないと0ベースで忘れてしますので、触りだけメモ。
環境はMac想定です。すみません。

前提知識

  • React NativeはReactを使ってクロスプラットフォーム(iOS, Android)開発を行うためのしくみ
  • 開発ツールとしてはexpoか、react-native-cliのいずれかを利用するのが一般的
  • expoは簡単だが限られた範囲での開発となる。react-native-cliは制限は無くどんなニーズにも対応
  • ただ多くの場合expoの範囲で事足りることが多いのでここではexpoを利用する
  • なお、ejectすることでexpoの制限を超えることができる(もちろん失うものもあるが)

環境構築

  • node.jsをインストールしておく(必須)
  • watchmanをインストールしておく
  • yarnをインストールしておく
  • XcodeとAndroid Studioもインストールしておいたほうがいい
    • Android Studioではエミュレータを作成し、起動できるようにしておく

expoのインストール

npmでglobalにインストールします。

npm install -g expo-cli

作業場+雛形作成

initコマンドでプロジェクトを作成します。
下記の場合、expo_sampleというフォルダが作成され、その中に雛形が生成されます。

expo init expo_sample

いくつか質問をしてきます。
まずは、テンプレートの選択。まあ、blankでよいかと。

? Choose a template: (Use arrow keys)
  ----- Managed workflow -----
❯ blank         minimal dependencies to run and an empty root component
  tabs          several example screens and tabs using react-navigation
  ----- Bare workflow -----
  bare-minimum  minimal setup for using unimodules

次にhome screenに出すapp名を入れろ!と言われるので、まあ、プロジェクトと同じexpo_sampleとでもしておきます。

? Choose a template: expo-template-blank
? Please enter a few initial configuration values.
  Read more: https://docs.expo.io/versions/latest/workflow/configuration/ › 50% completed
 {
   "expo": {
     "name": "<The name of your app visible on the home screen>",
     "slug": "expo_sample"
   }
 }

Yarnが見つかればYarnを使うか?と聞かれます。とりあえずYesで。

? Yarn v1.13.0 found. Use Yarn to install dependencies? (Y/n)

ディレクトリ構造

上記の操作が完了すると、下記のような雛形構造が生成されます。
App.jsをいじって開発することになります。

スクリーンショット 2019-06-04 4.37.38.png

動作確認

何かコーディングする前に、初期状態でうまく動作するか確認しておくといいでしょう。
プロジェクトフォルダにおいて下記コマンドを実行します。

expo start

するとブラウザが起動し、下記の画面が起動します。

スクリーンショット 2019-06-04 4.42.30.png

この画面を利用して実機によるテスト、エミュレータによるテストが可能です。

実機によるテスト

実機でテストをしたい場合はiOSもしくはAndroidでexpoアプリをインストールして、アプリを利用してQRコードを読み取ることでテストできます。

iOSではカメラでQR読めば「アプリを起動するか?」聞いてきます。

エミュレータによるテスト

上記ブラウザ画面の左メニューで「Run on Android device/emulator」もしくは「Run on iOS simulator」を選びます。ここではiOSシミュレータを利用してみます。

下記のようなものが表示されればOKです。

スクリーンショット 2019-06-04 4.49.26.png

最低限の実装:Styleをインラインに記述

サンプルコードが長くなるので、外部設定されたSytleをインラインに記述してみます。

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

export default class App extends React.Component {
  render() {
    return (
+      <View style={{flex:1, paddingVertical:80, alignItems:'center'}}>
        <Text>Open up App.js to start working on your app!</Text>
      </View>
    );
  }
}

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

最低限の実装:Buttonを配置。クリックしてアラート表示(ついでにlog出力)

何は無くともボタンは必要。onPressに関数を設定することでその内容が実行されます。
まずはクロージャを利用。

App.js
import React from 'react';
+//Buttonを追加
+import { StyleSheet, Text, View, Button } from 'react-native';

export default class App extends React.Component {
  render() {
    return (
      <View style={{flex:1, paddingVertical:80, alignItems:'center'}}>
        <Text>Open up App.js to start working on your app!</Text>
+        <Button
+          title="Click Me"
+          onPress={()=>{
+            alert("アラート表示");
+            console.log("コンソールログ")
+          }}
+        />
      </View>
    );
  }
}

実行すると、下記のような感じ。

スクリーンショット 2019-06-04 5.07.32.png

console.log()はexpo startさせたコンソールに表示されているはずです。

なお、外部関数化することもできます。その場合は、this.functionで呼び出し。

App.js
import React from 'react';
//Buttonを追加
import { StyleSheet, Text, View, Button } from 'react-native';

export default class App extends React.Component {
  render() {
    return (
      <View style={{flex:1, paddingVertical:80, alignItems:'center'}}>
        <Text>Open up App.js to start working on your app!</Text>
        <Button
          title="Click Me"
+          onPress={this.showAlert}
        />
      </View>
    );
  }

+  //アラート表示
+  showAlert = () => {
+    alert("アラート表示");
+    console.log("コンソールログ");
+  }

}

最低限の実装:変数(state)の利用

Reactにはstateとpropsという2つの変数を扱う仕組みがあります。まずは、state。
あるリアクトコンポーネント(ここではApp.js)内で利用する変数はすべてstateにおいて定義されている必要があります。
また、変数の更新は

name = "hoge";

というような形はとれず、

this.setState({name: "hoge"});

というような形でsetState()を利用して更新する必要があります。

なお、1つのアプリにApp.js, A.js, B.jsと複数のコンポーネント(画面)が存在する場合、原則としてコンポーネント間で値を共有することができないため、別途Redux等のしくみを利用する必要があります。

以下、サンプルです。
stateにname, ageを表示し、初期値としてhoge, 33を定義しています。
ボタンをクリックしたら、名前がfooに切り替わるというものです。

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

export default class App extends React.Component {

+  //stateを定義
+  state = {
+    name: "hoge",
+    age: 33
+  }

  render() {
    return (
      <View style={{flex:1, paddingVertical:80, alignItems:'center'}}>
+        <Text>こんにちは。{this.state.name}さん。</Text>
        <Button
          title="Change Name"
+          onPress={this.changeName}
        />
      </View>
    );
  }

+  //name変更
+  changeName = () => {
+    this.setState({
*      name: "Foo"
+    });
+  }

}

動作サンプル。

スクリーンショット 2019-06-04 5.28.40.png

最低限の実装:変数(Props)の利用

propsはタグコンポーネント間で値を受け渡す仕組みです。
コードを見たほうが早いでしょう。という関数によるカスタムタグを定義し、カスタムタグに対しpropsで初期値を渡しています。

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

export default class App extends React.Component {

  //stateを定義
  state = {
    name: "hoge",
    age: 33
  }

  render() {
    return (
      <View style={{flex:1, paddingVertical:80, alignItems:'center'}}>
        <Text>こんにちは。{this.state.name}さん。</Text>
        <Button
          title="Change Name"
          onPress={this.changeName}
        />
+        <Hello to="Bob"/>
+        <Hello to="Tom"/>
      </View>
    );
  }
  //アラート表示
  changeName = () => {
    this.setState({
      name: "Foo"
    });
  }
}

+function Hello(props){
+  return (
+    <Text>Hello. {props.to}!</Text>
+  );

}

実行サンプル

スクリーンショット 2019-06-04 5.37.24.png

最低限の処理:Input処理

React(Native)で「え?」と思わされるのがForm等でのInput処理です。
結論から言えば、TextInput等の入力系コンポーネントを配置しただけでは値が変更できません。
下記コードはstateで初期値text1を配置し、それをInputTextの初期値として設定しているコードです。
下記コードを実行して、テキストを編集してみてください。できないはずです。

App.js
import React from 'react';
+//TextInputを追加
+import { StyleSheet, Text, View, Button, TextInput } from 'react-native';

export default class App extends React.Component {

  //stateを定義
  state = {
+    text1 : "placeholder"
  }

  render() {
    return (
      <View style={{flex:1, paddingVertical:80, alignItems:'center'}}>
        <Text>入力してください</Text>
+        <TextInput
+          value={this.state.text1}
+        />
        <Button
          title="Entry"
          onPress={this.entry}
        />
      </View>
    );
  }
  //TextInputの内容をアラートで表示
  entry = () => {
    alert(this.state.text1);
  }
}

実行サンプル

スクリーンショット 2019-06-04 5.50.23.png

編集可能とするためには、onChangeText()を定義して、テキストが変更される度、stateを更新する処理が必要です。
この辺を簡略化してくれるコンポーネントもありますが、これが基本となります。

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

export default class App extends React.Component {

  //stateを定義
  state = {
    text1 : "placeholder"
  }

  render() {
    return (
      <View style={{flex:1, paddingVertical:80, alignItems:'center'}}>
        <Text>入力してください</Text>
        <TextInput
          value={this.state.text1}
+          onChangeText = {(t) => this.setState({text1:t})}
        />
        <Button
          title="Entry"
          onPress={this.entry}
        />
      </View>
    );
  }
  //アラート表示
  entry = () => {
    alert(this.state.text1);
  }
}

実行サンプル

スクリーンショット 2019-06-04 5.58.12.png

最低限の実装:カッコいいコンポーネント(react-native-elements)を使う

npm install react-native-elements

なぜか再度npm installしないと使えません。。。

npm install

yarn add react-native-elementsだと、1回でOKみたい。

そして実装。上と同じ機能をreact-native-elementsのコンポーネントで置き換えてみました。

バージョンアップしてFormInput, FormLabel等はInputに統合されたみたい。。。

App.js
import React from 'react';
//Buttonはかぶるの消す
import { StyleSheet, Text, View, TextInput } from 'react-native';
//使うコンポーネントをimport
import { Card, Button, Input} from 'react-native-elements';

export default class App extends React.Component {

  //stateを定義
  state = {
    text1 : "placeholder"
  }

  render() {
    return (
      <View style={{flex:1, paddingVertical:80}}>
        <Card title="入力してね">
          <Input
            value={this.state.text1}
            label="text1"
            errorMessage="error"
            onChangeText={(t)=>{this.setState({text1:t})}}
          />
          <Button
            title="Entry"
            buttonStyle={{marginTop:30}}
            borderRadius={20}
            onPress={this.entry}
          />
        </Card>
      </View>
    );
  }
  //アラート表示
  entry = () => {
    alert(this.state.text1);
  }
}

実行サンプル

スクリーンショット 2019-06-04 6.30.01.png

まだいろいろあるけど、必要に応じて随時追加します。

73
55
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
73
55