React Native for Androidでアプリを作る


[React Native for Android: How we built the first cross-platform React Native app | Engineering Blog | Facebook Code](https://code.facebook.com/posts/1189117404435352/)
[React Native | A framework for building native apps using React](http://facebook.github.io/react-native/)

# Setup

### Android SDKの追加

Android SDK Managerで以下をinstall

- Intel x86 Atom System Image (for Android 5.1.1 - API 22)
- Intel x86 Emulator Accelerator (HAXM installer) 

### react-nativeの準備

いくつかinstallする

```sh
npm install -g react-native-cli
brew install watchman
brew install flow
```


# 新しいProjectを始める

`react-native`コマンドを使ってprojectを作る

```sh
react-native init ReactSampleProject
```

これを実行するには`react-native`の`run-android`コマンドを使用する

```sh
cd ./ReactSampleProject
npm i
react-native run-android
```

ここでBuild Toolsの23.0.1が入っていないとエラーが出て終了する

```sh
$ react-native run-android
Starting JS server...
Building and installing the app on the device (cd android && ./gradlew installDebug)...

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> failed to find Build Tools revision 23.0.1
```

ちゃんと入れてから再度走らせると、gradleのタスクが走っている様子が流れる
`watchman`と`flow`をHomebrewでinstallしていないとReact Packagerのwindowではエラーが出て、アプリは赤いエラー画面だけ表示される

![20150915_092431.png](https://qiita-image-store.s3.amazonaws.com/0/280/52493ccb-f433-fbb3-11d3-b1dc363afe16.png "20150915_092431.png")




ちなみに一度`run-android`で成功すると

```sh
$ react-native run-android
JS server already running.
Building and installing the app on the device (cd android && ./gradlew installDebug)...
...
```

となり、普通のAndroidプロジェクトとしてビルド出来るようになります

![20150915_094130.png](https://qiita-image-store.s3.amazonaws.com/0/280/84c99075-76a3-6783-d3bf-b0c05a69657f.png "20150915_094130.png")


# 実装

手元のindex.android.jsを編集する
例えば以下のように書き換える
参考：[Tutorial – React Native | A framework for building native apps using React](http://facebook.github.io/react-native/docs/tutorial.html#render-a-movie)

```js:index.android.js
'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  TextInput,
} = React;

var ReactSampleProject = React.createClass({
  getInitialState: function() {
    return {text: "sample"};
  },
  render: function() {
    var MOCKED_MOVIES_DATA = [
      {title: 'Title', year: '2015', posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'}},
    ];
    var movie = MOCKED_MOVIES_DATA[0];
    return (
      <View style={styles.container}>
       <Text>{this.state.text}</Text>
       <Text>{movie.title}</Text>
       <Text>{movie.year}</Text>
       <Image style={styles.thumbnail} source={{uri: movie.posters.thumbnail}} />
       <TextInput onChangeText={(text) => this.setState({text})} value={this.state.text} />
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  thumbnail: { width: 30, height: 30, },
});

AppRegistry.registerComponent('ReactSampleProject', () => ReactSampleProject);

```

## 実機での起動

GenymotionやAVDなら何も設定しなくても動作しますが、実機の場合は動きませんでした
Genymotion等はF2押すとmenuが開いて[Reload JS]出来ますが、実機の場合はmenuボタンの代わりに
端末を振るとmenuが表示されます
表示したmenuで[Dev Settings}から[Debug server host for device]を選択し、`react-native`を動かしたPCのipアドレスを指定するとJSが読み込めて起動します


![Screenshot_2015-09-16-09-26-44.png](https://qiita-image-store.s3.amazonaws.com/0/280/23f99cca-9ac9-b1d9-b612-e05226476552.png "Screenshot_2015-09-16-09-26-44.png")

# コンポーネントを作る

タップすると入力されたテキストがToastに表示されるボタンを作ってみる

```js:ToastButton.js
var React = require('react-native');
var {
  TouchableNativeFeedback,
  StyleSheet,
  ToastAndroid,
  View,
  Text,
} = React;

var ToastButton = React.createClass({
  propTypes: {
    text: React.PropTypes.string.isRequired,
  },
  render: function () {
    return (
      <TouchableNativeFeedback
        onPress={() =>
          ToastAndroid.show(`Your input is ${this.props.text}`, ToastAndroid.SHORT)}
        background={TouchableNativeFeedback.SelectableBackground()}
        style={styles.toastButton}>
        <View>
          <Text>Tap me</Text>
        </View>
      </TouchableNativeFeedback>
    );
  },
});

module.exports = ToastButton;

```

そして

```js:index.android.js
<ToastButton text={this.state.text}/>
```

を適当なところに差し込めば良い
表示された"Tap me"をタップするとこうなる
![Screenshot_2015-09-16-09-33-17.png](https://qiita-image-store.s3.amazonaws.com/0/280/b82444e9-0ac5-11cf-5038-dabf1024b04d.png "Screenshot_2015-09-16-09-33-17.png")

Androidのカスタムビューにあたるものがコンポーネントという形で簡単に作れる

# 所感

まだ足りないものが多くて厳しいという印象
画面遷移どうやるんだろう、って思ったけどReactだからSPAっぽく書き換えていけば良いからIntentは無いのかな
デザインを変更するにはCSSっぽいけどちょっと違う独自のstyleを使っていく必要があるが、ドキュメントも少なくて大変
いわゆるカスタムビューを作るのが簡単なので、慣れればxmlとjavaで書くよりも速くささっと画面作れそう

[Facebookのオープンソース「React Native for Android」でクロスプラットフォーム開発が簡単になる | TechCrunch Japan](http://jp.techcrunch.com/2015/09/15/20150914react-native-android/)
この記事によると3ヶ月でAndroidアプリ作ったとあるので、React理解してるエンジニアがちゃんと使えばそれなりになるのかも知れないが、Titaniumみたいなものかと認識している