# React-NativeでExpo+unstated+firebase(web版)で~~出会い系~~SNSアプリを作る話 ``` 私は奮起した。必ず、モバイルアプリを作らねばならぬと決意した。 私にはJavascriptがわからぬ。私は、Windowsアプリのプログラマである。 VisualStudioを見つめ、C#と遊んで暮して来た。 けれども昨今の技術の隆盛に対しては、人一倍に敏感であった。 ``` この記事はクロスプラットフォームのアプリがそれなりに動く予感がするところまでを掲載します。 特に、採用した基幹技術とその組み合わせ方についてメモを残します。 ちなみにこの記事を最後まで頑張るとこういうアプリが作れます。 あまり細かい解説をしないので、コーディングって何?っていう人が読むと辛いかもしれません。 需要があれば追記したりコメント返すのでお知らせください。 まずは数日かけて情報収集した結果として採用した基幹となる技術について ## React-Native 私はC#のエンジニアなので最初はXamarinで頑張っていた。(過去形、2018年初頭のことである) 地獄を見た原因はいくつかあったが、xamarinがマイクロソフトに~~乗っ取られた~~買収された直後だったのでドキュメントも何もない手探りの状態だったので挫折したというのが大きい。 react-nativeは2019年秋の今最もホットなツールであり、ドキュメントも豊富で、開発がしやすい。と思う。 特にアプリ開発をまた始めようと思った大きなモチベーションとなったのは ここ1年のライブラリ周りのアップデートや、直近の日付で生成される数々の~~人柱の記事~~ もとい、ぐぐれば先人が誰かトライしてくれていて、あわよくば答えが見つかるなんて、本当に幸せなことである。 ## expo 実際の商用プロジェクトに限って言えば、どの程度まで製品クオリティを担保できるか、実現可能性があるかなどまで測定がしづらく採用されているケースがそこまで多くないのだが、私のような弱小おひとり様プログラマーであれば、expoほどお手軽で簡単にマルチプラットフォームの開発が可能なツールはない。 ただ、サンプルコードなんかを探すときも個人の開発ブログなどがググり先の中心になるのがつらい。(実際辛かった) ## redux reduxはstate管理の素晴らしいライブラリだ。これは疑いようもない。 世界で一番愛用され、情報量も多く、大規模システムに向いている。 しかし、学習コストが高い+プロトタイプ制作が苦手なreduxは個人開発やスタートアップには適さない。と思う。 Reduxを用いて実装するのなら、component/container/action/reducerについての理解から始めなければいけないし、 構造が多層的なのでサンプルをコピペしたりしてなんとかなる話ではなくなってしまう。そもそもコード量が多い。 一方でunstatedでは極端な話TodoContainerだけあればstate管理ができる。 つまり、「簡単さ」という点においてとにかく優れているのがunstatedと言える。 大規模プロジェクトにする予定もなし、今回はunsteated-nextを採用する。 (ちなみにunstatedとunstated-nextで迷ったらnextでよい。 あんまちゃんと読んでないけどgithubの公式レポジトリにあるreadme曰くnextは上位互換のようだ) 参考にした記事:状態管理はreduxじゃなくてunsteadにしよう https://qiita.com/kaba/items/b05f680f850dd46548f3 ## web版のfirebaseをつかおう React NativeからFirebaseを使う際は、 firebaseモジュール(WebSDK) react-native-firebaseモジュール どちらかのnpmモジュールを導入することになる。 ざっくり解説すれば、firebase はJavaScript上のみで動くのに対し、 react-native-firebase はiOSおよびAndroidネイティブのSDKをReact Native用にラップしたものらしい。 ここのポイントは下記に尽きる **・firebase-reavtnativeはnative依存があるのでバージョンアップでこわれやすいこと。** 試しに「react-native バージョンアップ 動かない」でググれば即座にWelcome to hellである。 それでも信用できない人はGithubで適当にスターの多いreact-nativeのサンプルをcloneして自分でバージョンアップ作業をしてみるとよい。Too young to dieできること請け合いだ。 どこかの記事で「バージョンアップ対応が早いのと、パフォーマンス面でも優れているらしいので、React NativeからFirebaseを使うときは、基本的に react-native-firebase を導入するといいでしょう。」という意見も見たのだが、、、 詳しくはそれぞれのレポジトリのREADMEを見比べたらいいと思うけど、今回はメンテのしやすさを重要視した。 私の作りたいレベルのアプリであれば対応表などを見比べても機能的に遜色がない。 ていうか、react-native-firebase はネイティブのSDKを使うのだから、Expoでは使えないと思っていい。(未検証) --- # 作業開始 ## まずはexpoとreact-navigationでアプリの骨格(テンプレート)を作る。 sudo npm install expo-cli --global //間違いやすいので補足:昔はExpo XDEというGUIツールが配布されていたらしいけど、2018年9月頃にExpo CLIに置き換わったとのこと。ググるときは注意しよう。 mkdir sample_expo cd sample_wxpo expo init ? Choose a template: **blank** cd [url] nmp start ここでexpo startすれば簡単な2画面のアプリが立ち上がるはず。 もうちょっと複雑な画面構成が欲しいのだがそれにはreact-navigationを使う必要がある。 react-nativeで画面遷移させるならこのモジュール択一だ。 しかして、ここでtemplateにはいくつか選択肢があった。だがしかしtemplate-tabを選択して地獄をみたので合わせてお伝えする。 いろいろいじってみたけどどうしてもscreenが増やせなかった(世の中のサンプルと記述の形が合致しない)のだ。 というのはreact-navigationの機能を使うためには 初期画面を1つの「画面」としてreact-navigationに認識させる必要がある。 template-tabを選択すると初期画面が純粋な関数で表現されてしまい、これをReact Componentにコンポーネント化する作業が必要になる。 JavascriptとReactに精通している人なら問題ないのかもしれないが、サンプルかき集めごった煮野郎の私にはどう頑張っても無理だった。1から作ったほうがはやいという結論にたどり着くのに3日かかった。 ちなみに僕の頭で単純に上記の作業(template-tabの初期画面のコンポーネント化)をすると下記のエラーにぶちあたってにっちもさっちもいかなくなった。下記の内容が理解できる人はtemplate-tabでもよいのではないかと思う。あるいはreduxを採用してる人。 https://qiita.com/recordare/items/9d563d7b2de76d335977 さよならテンプレ。とはいえblankテンプレートを選択したといっても1から作るつもりもなく https://github.com/react-navigation/react-navigation/blob/master/example/src/StacksInTabs.tsx の内容をそのままコピることで事なきを得た。合掌。 (リンク先のソースは今を輝くTypeScript形式の記述であることに注意) ※補足:footerTabのアイコンを変えたいときは下記から欲しいアイコンを探そう https://expo.github.io/vector-icons/ ## firebaseの導入(テキスト、写真データの保存) 続いてはSNSアプリらしく入力したテキストや写真をサーバに保存させる機能が欲しい。ユーザ認証も必要になる。 https://github.com/EvanBacon/firebase-instagram あたらしいscreenを1つ作って、上記リポジトリのNewPost.jsの内容をコピペする。 それからfire.jpと付属するソースを移行すれば動いた。簡単。 一部のソースが今のexpoのバージョンと合致していないのでモジュールの再インストールやソース修正が必要になった。 コンソールのエラーメッセージ通り直せば動くようになる。 ちなみにいろいろモジュールが足りないといってエラーが出ると思うが、ここで大切なこととして、 今回はExpoを使っているので、互換性があるバージョンを選択するため以下のようにnpmではなくExpoのコマンドでインストールします。 expo install react-native-gesture-handler react-native-reanimated ここまで完了した段階ではユーザは匿名ユーザのままである、ログインページは後から作ろう。 firebase側の設定などは上記レポジトリのチュートリアルの参照されたし。 わかりにくいところとして RealtimeDetabaseとcloudの選択肢があるが、cloudが上位互換なので択一のようだ。(2019.9時点) リージョン設定はasia-northeast1。asia-northeast2が大阪らしいけど、まだどうも遅いらしい。(らしい) プロジェクトを作ったら「ウェブアプリにFirebaseを追加」を選択すること。 間違ってもnativeプロジェクト側に設定しようとしてexpo exit?してはいけない。 ## firebaseの導入(ユーザ認証) ## unstated-nextの導入 npm install --save unstated-next https://github.com/jamiebuilds/unstated-next ## UIの設定(tinder-clone,gift-chat) すでに用意したNavigationのscreenに下記リポジトリの画面をコピペして乗せていこう。 いろいろモジュールが足りないといってエラーが出ると思いますが(二度目)。 とりあえず画面要素タグでまるっと囲んでコピピしたらなんと動く。ラッキー。 loadResourcesAsyncにフォント読み込みを追記するのがちょっとわかりにくいかも。 'tinderclone': require('./assets/fonts/tinderclone.ttf'), Tabbarの中はexpo仕様のままでいきたいので ## おわりに 勇者は、ひどく赤面した。