React Nativeで
開発するマルチプラットフォームアプリ
Masayuki Iwai @myb
#iosdcrc
+Redux
React Nativeで
開発するマルチプラットフォームアプリ
Masayuki Iwai @myb
#iosdcrc
自己紹介
岩井雅幸 @myb



モバイル・アプリケーション・エンジニア

@Unity Technologies Japan

それ以前はWebデザイン・開発、Flashコン
テンツ制作、iOSアプリ、ゲーム制作など
著書に「uGUIではじめる Unity UIデザイン
の教科書」
React Native
Unity Meetup
• Unityユーザーのためのイベント

アプリ(フルReact Native)
• 既存のUnity県人会議という

イベント情報サイトがベース
• 2016年10月iOS/Androidリリース
• 設計〜プロトタイプ制作約2ヶ月、

iOS実装+サーバーAPIで約3ヶ月、

Android実装+デバッグで約1ヶ月
React Native
採用のモチベーション
時は2016年初頭…
• マルチプラットフォーム📱(iOS/Android)
• ネイティブのパフォーマンス、気持ちいい操作感⚡
• 開発は少人数(実質1人#)
イベントアプリ(Unity Meetup)の制作にあたって
フレームワークを検討…
Cordova、Titaniumなども検討

(もちろんUnityも)
• Cordova - やはりWebViewベースなので…
• Titanium - 以前流行ってたけど、オワコン感ある…
• Unity - オーバースペックな上、UIではネイティブのパフォーマンスは出ない
• /* Xamarin.Formsはこのとき存在を知らなかった😝 */
React Native
• JavaScriptCore上で動作し、ネイティブのビューを生成

→ つまりほぼネイティブ👍
• コードの大半を共有しつつ、各プラットフォーム標準のUIに準拠できる🙌
• Facebook Group Appなどの実績がある💪
• FacebookのOSSで安心感がある💪
• これから流行りそう!😆
ざっくりReact Native
(+Redux)
React
• Facebook製のJavaScriptライブラリ

(🌟77.6k)

https://reactjs.org
• コンポーネントベースでUI(ビュー)を構築
• JSX - スクリプト中にDOMでビューを記述
• propsとstateに基づいてrender関数で
ビューを描画
• propsやstateが変化すると、自動的にビュー
の差分のみが再描画される
import React from 'react'
class App extends React.Component {
state = {
label: 'It works!',
}
render() {
return (
<div className="container">
<div className="content">
<h1 className="name">
{this.props.name}
</h1>
<p className="label">
{this.state.label}
</p>
</div>
</div>
)
}
}
Redux
• 状態管理のためのJavaScript

ライブラリ(🌟34.6k)

http://redux.js.org
• データの流れを1方向にし、

状態の保持と更新を集約

→ 複雑なアプリケーションの品質と

  メンテナンス性の向上
• Swift界においてもReSwiftとして実装
されるなど、注目のアーキテクチャ
Store
UI

(ビュー)
Action
Reducer
Dispatch
更新
イベント
更新されたState
State

(状態)
React+Redux
• react-redux - ReduxのReactバインディング(公式)

https://github.com/reactjs/react-redux
• Reactはコンポーネントの状態(propsとstate)によってビューを描画する

ので、相性が良い
• Container ComponentとPresentational Component

- Container Component - Reduxと連携する

(StoreからStateを得たり、Actionをdispatchする)

- Presentational Component - 直接Reduxに関与せず、props経由でのみ

データを受け取る(ビューの描画に専念)
React Native
• Reactを用いてネイティブアプリケーションを作成するためのライブラリ

(🌟54.2k)

https://facebook.github.io/react-native/
• iOS/Androidに対応

Microsoft製react-native-windowsでWindows(UWP/WPF)にも対応
• JavaScriptCore上で動作し、ネイティブのビューを生成
• 標準でView、Text、Image、ScrollViewなどのコンポーネントを提供
React Native
import React from 'react'
class App extends React.Component {
state = {
label: 'It works!',
}
render() {
return (
<div className="container">
<div className="content">
<h1 className="name">
{this.props.name}
</h1>
<p className="label">
{this.state.label}
</p>
</div>
</div>
)
}
}
import React from 'react'
import { ScrollView, View, Text } from 'react-
native'
class App extends React.Component {
state = {
label: 'It works!',
}
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.content}>
<Text style={styles.name}>
{this.props.name}
</Text>
<Text style={styles.label}>
{this.state.label}
</Text>
</View>
</ScrollView>
)
}
}
React Native

ここが良い!
コンポーネントベースが良い
• コンポーネント単位でテストできる
• 開発が進んで複雑になった部分を

後からでも分離しやすい
• ファイル名でプラットフォームごと
にコンポーネントを読み分けられる

→ (例)Foo.ios.jsとFoo.android.js
import React from 'react'
import { ScrollView, View, Text } from
'react-native'
class App extends React.Component {
state = {
label: 'It works!',
}
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.content}>
<Text style={styles.name}>
{this.props.name}
</Text>
<Text style={styles.label}>
{this.state.label}
</Text>
</View>
</ScrollView>
)
}
}
コンポーネントベースが良い
• コンポーネント単位でテストできる
• 開発が進んで複雑になった部分を

後からでも分離しやすい
• ファイル名でプラットフォームごと
にコンポーネントを読み分けられる

→ (例)Foo.ios.jsとFoo.android.js
import React from 'react'
import { ScrollView, View, Text } from
'react-native'
class App extends React.Component {
state = {
label: 'It works!',
}
render() {
return (
<ScrollView style={styles.container}>
<View style={styles.content}>
<Text style={styles.name}>
{this.props.name}
</Text>
<Text style={styles.label}>
{this.state.label}
</Text>
</View>
</ScrollView>
)
}
}
コンポーネントベースが良い
• コンポーネント単位でテストできる
• 開発が進んで複雑になった部分を

後からでも分離しやすい
• ファイル名でプラットフォームごと
にコンポーネントを読み分けられる

→ (例)Foo.ios.jsとFoo.android.js
import React from 'react'
import { ScrollView } from 'react-native'
import ContentView from 'ContentView'
class App extends React.Component {
state = {
label: 'It works!',
}
render() {
return (
<ScrollView style={styles.container}>
<ContentView
style={styles.content}
name={this.props.name}
label={this.state.label}
/>
</ScrollView>
)
}
}
Flexbox/スタイルシートで思い通りのレイアウト
• React Nativeのビューのレイアウトは

Flexboxに基づく
• Auto Layoutと違い、Web的なアプ
ローチでレスポンシブなデザインが可
能
• ビューの属性はスタイルシートで記述

- レイアウトに関する属性

(flex, width, height, margin etc.)

- 視覚的な属性

(borderWidth, opacity etc.)
Flexbox/スタイルシートで思い通りのレイアウト
• React Nativeのビューのレイアウトは

Flexboxに基づく
• Auto Layoutと違い、Web的なアプ
ローチでレスポンシブなデザインが可
能
• ビューの属性はスタイルシートで記述

- レイアウトに関する属性

(flex, width, height, margin etc.)

- 視覚的な属性

(borderWidth, opacity etc.)
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5fcff',
},
label: {
fontSize: 30,
fontWeight: 'bold',
color: '#262729',
},
box: {
justifyContent: 'center',
alignItems: 'center',
width: 100,
height: 100,
backgroundColor: '#f1f3f4',
},
});
デバッグもしやすい
• 再ビルド不要で⌘+Rでjsbundleをリロードできるので(ブラウザ感覚)、

トライ&エラーが楽😄

※デバッグビルド
• Chrome上で動くReact Native Debuggerが付属

→ ブレイクポイントも張れるし、スタックトレースも見られる
• redux-loggerを使うと、Actionによって変更される前後のStateを見られる
React Native対応のパッケージもたくさん
• 豊富なJavaScriptライブラリを利用できる - moment、numeral etc.
• 標準で提供されていない機能でも、ググると大抵パッケージがある

→ SFSafariViewController、iBeacon、Firebase etc.
• なくても、ネイティブモジュールを簡単に作れる

→ 最近react-native-safe-areaというモジュールを作った

https://github.com/miyabi/react-native-safe-area
• コンポーネントベース
• 思い通りのレイアウト
• デバッグしやすい
• パッケージもたくさん
つまり、React Nativeなら
動くものを早く作れる!😆
React Native

ここがツライ…!
JavaScriptゆえのつらみ
• 型のない世界

- とはいえTypeScriptやFlowがある

- jsファイルのままアノテーションを追加できて

静的にチェックできるFlowがいい感じ

- バージョンの組み合わせによってエラーに

なったりならなかったりすることも…
• 自由度が高すぎていろんなスタイルで書け
ちゃう

- 開発メンバーが増えたときが心配

- Airbnbが公開しているスタイルガイドを

ベースにeslintを設定

https://github.com/airbnb/javascript
import React from 'react'
import { ScrollView } from 'react-native'
import ContentView from 'ContentView'
class App extends React.Component {
state = {
label: 10000,
}
render() {
return (
<ScrollView style={styles.container}>
<ContentView
style={styles.content}
name={this.props.name}
label={this.state.label}
/>
</ScrollView>
)
}
}
JavaScriptゆえのつらみ
• 型のない世界

- とはいえTypeScriptやFlowがある

- jsファイルのままアノテーションを追加できて

静的にチェックできるFlowがいい感じ

- バージョンの組み合わせによってエラーに

なったりならなかったりすることも…
• 自由度が高すぎていろんなスタイルで書け
ちゃう

- 開発メンバーが増えたときが心配

- Airbnbが公開しているスタイルガイドを

ベースにeslintを設定

https://github.com/airbnb/javascript
import React from 'react'
import { ScrollView } from 'react-native'
import ContentView from 'ContentView'
type Props = {
name: string, // string(nullやundefinedは許可されない)
};
type State = {
label: ?string, // string(null許可)
};
class App extends React.Component<Props, State> {
state = {
label: 10000, // ERROR!!
}
render(): React.Node {
return (
<ScrollView style={styles.container}>
<ContentView
style={styles.content}
name={this.props.name}
label={this.state.label}
/>
</ScrollView>
)
}
}
バージョンアップが早い
そのうえ変更も多い
• この1年半でも、0.26.0 → 0.49.1(2017年10月現在最新)
• 大体のマイナーバージョンアップはBreaking Changesを含んでいる

- 使っているパッケージによってはビルドエラーになることもあるので、

直したりPR送ったり…

- そのままメンテナンスされずに放置されるパッケージももちろんある…
主要なコンポーネントが結構deprecatedになる
• Navigator - 0.44.3でdeprecated😢

- NavigatorIOSは残っているがAndroidで使えない

- 公式でもreact-navigation(react-community)やnative-navigation
(Airbnb)を推奨
• ListView - 0.48.0でdeprecated😢

- FlatList、SectionListに移行
• MapView - 0.44.3でdeprecated😢

- react-native-maps(Airbnb)推奨
良くも悪くも

Facebookに依存している
• 少し前にApache Software FoundationがFacebookプロジェクトを

使用禁止にして話題になっていた

- ライセンスの条項が問題になっていたが、先日あらためてMITライセンスにすると

発表されてひと安心😌

https://code.facebook.com/posts/300798627056246
まとめ
React Native(+Redux)
• 小規模なプロダクトあるいはチームでのマルチプラットフォームアプリ開発に
最適😆
• 短期間で動くものが作れる - プロトタイプ制作にも😄
• 規模が大きくなってもスケールはする😎
• が…色々とつらみが出てくる😢
• つらみを乗り越えて頑張るぞい!👊
Thank you.

React Nativeで開発するマルチプラットフォームアプリ