2019の10日目です。テックリード/フロントエンドエンジニアの井上(@ashimon83)です。相変わらずスマブラはネスしか使いません。相変わらず非VIPです。Native絡みで記事を書いてみようと思います。Native使ってるの?はい、実は使ってます。どこで使ってるの?弊社の運営するアソビュー!では様々な遊びの施設のチケットをお得に購入することができるのですが、決済は事前に行い、一部のチケットに関してはQRコードを提示するだけで簡単に入場することが出来ます。Nativeで開発しました。弊社ではスピード感を持ってゲスト(ユーザー)へ便利でお得な体験を届けるため、企画が決まってから開発、リリースするまでのスピードをなるべく早くすることを心がけています。今回このQRコード着券についても当然ながら早くゲストに届けたい!という思いはあり、要件的にネイティブアプリでの提供が必須ながらもその時点ではネイティブアプリのエンジニアや体制がありませんでした。Nativeで作ることを決めました。Native自体の特徴やメリット・デメリットなどは世の中に情報が出回ってると思いますのでここでは改めて詳細には書きません!弊社としては下記メリットが大きいです。Native自体はチュートリアル程度の知識しか無かった私が3週間程度で一気に開発して無事リリースすることができました。いえやはり普通にWebのReact開発とは違う点なども多くあり、それなりにハマったところもあったので、今回はそれらのWebとNativeの同じところ、違うところについてまとめてみます。※なお今回expoを採用してますのでその前提です。Viewレイアウト周りには特に苦戦させられます。Componentに関しては大きな違いはありません。JSX含めWebと同じ感覚で書けます。v0.59から導入されました。v33がテスト直前の6/6にリリースされるという。違うところ細かな点でdivが使えないレイアウトはViewタグ、文字列はTextタグで囲う必要がある、など。webのReactと平行で開発してると間違えてしまう。styleとほぼ等しい書き方になります。Webでは非推奨とされてるやり方ですね。colomnが効いています。Textが改行すると高さの計算がうまく行かないのか隠れてしまったりなど微妙に普通にWebと挙動が違うところがちらほらあります。Android、iOSでそれぞれ対応しているものしていないUIのコンポーネントがあるので使い分ける必要がある例)トーストのUIがiOS側で無かったのでAlertで代替してます。RoutingRoutingを管理するためには何かしらライブラリを用いる必要があります。Navigationを採用しています。同じところあまりないと言えばないし、あると言えばあるという感じですが、SPAの画面遷移に概念としては似ていますかね。(俗っぽい言い方だと)アプリっぽUIのWebとかネイティブアプリと同じUXを提供する場合は似たような作りや考え方になります。違うところタブナビゲーションによる遷移なのか、モーダルで出したいのか、でrouting部分の構築の仕方が変わってきます。アプリでよくある標準的なタブナビゲーションや全画面モーダル(っぽい動き)関してはreact-navigationのライブラリで賄ってくれます。Nativeの場合、例えば下にタブナビゲーションが有って上部が切り替わっていく+特定の画面については全画面モーダル(ヘッダーや)の場合下記のように階層構造を記載していくことになります。MainTabNavigatorreduxでrouting(navigation)の情報が取れない。これがかなり悩ましかったです。Webの場合、connected-react-routerを活用することでreduxの中でpathを取得したり、LOCATION_CHANGEのタイミングをアクションで捉えることが出来ましたが、そちらはできない(出来なくはないが推奨されない)です。Error出た際にエラーモーダルにnavigation遷移させたりしたかったのですがこういった事情のため諦めました。managementreduxを活用してますがこちらに関しては大きな違いは無いと思いました。mobxでも何でも使えると思います。やろうと思えばWebと共有するなんてこともできるかも、、(多分辛い)同じところredux、react-redux、redux-thunk含め動きます。HOCのconnectから書き換えられてないのですがredux-hooksも動くはず違うところここに関してはあまりないと思います。Localstorage同じところWeb標準のLocalStorage的なシンプルなkey-valueストレージとしてAsyncStorageを使います。使い勝手はほぼ同じです。key-valueでsetItem、getItemします。違うところAsyncStorageにはmultiGet、getAllKeysなどより便利に使える機能があります。これは後述のラッパーを書いて拡張する際に活用できます。アプリなのでオフラインでも使いたい、key-valueよりは少し複雑なデータ管理をしたい(SQLiteのようにローカルDBとして使いたい)という需要が当然ながら出てきますが、そうなるとAsyncStorageの素の機能だけだと少し足りません。それを解決するためのライブラリとしてはいくつかあり、特にrealmがmongoDBライクでKVSもRDBもサポートしており、ドキュメントも充実しており素晴らしいのですが、悲しいかなexpoはサポートしてません!(expoあるある)ということで今回は結局AsyncStorageをreact-native-storageのような(このライブラリ自体もlinkが必要なのでexpo環境では使えません)IFで使えるようなラッパーを書きました。mockここは標準というよりはうちではこうやってます、というところの紹介になります。同じところSPAでもアプリでもAPIと平行してクライアントサイド開発していると、APIがまだ出来上がってないのでIFだけ認識合わせてモックを利用して実装するケースがあると思います。Contructまでは出来てませんが、とりあえず固定のJSON用意しておいて画面表示できるようにするな手段をとります。違うところWebではwebpack-dev-serverのbeforeでAPIへのリクエストをproxyしてjsonファイルの内容に書き換えることでモックしています。functionsで簡易なAPIサーバーを立てています。deployを叩く感じです。startでローカルサーバー起動して手元の端末のexpoアプリでQRを読み込んで直接配信することができ、ホットリロードも効くのでほとんど同じ感覚で開発できます。ネイティブのビルドも不要なので、もうこれだけでexpo縛りで開発する強い動機になりますね。point置いたりできます。devtoolsと同様にstateの遷移をトレースすることも可能です。違うところexpoならWebと同じ感覚でローカル開発できます。