nFact

n!

バックエンドエンジニアが事前知識なしでReact Native(+ Expo)に入門して詰まったところ

この記事は?

ウェブクルー Advent Calendar22日目の記事です。
普段はJavaを書いているバックエンドエンジニアが、事前知識なしでReact NativeにExpoで入門したときに詰まったところについて振り返ります。

f:id:noko_k:20181221000922p:plain
この記事に書いてあるものは正解じゃないものも混じってそうなのですが、基本的にはこんな感じの気持ちでJSを書いています。※ あと、英語のドキュメント頑張って読めば書いてあることがほとんどです。積極的にリンクを貼っておりますのでそちらを確認してください。

誰向け?

私みたいな人

  • JavaScript自体はそれなりに書けて、npmぐらいならJavaScriptのツールが使える
  • プログラミングスキルはそれなりにある(他の言語とかで)
  • ターミナルの扱い自体は大丈夫
  • JSがっつり書いたことない
  • React NativeどころかReact自体ほとんどやったことない

そもそも

セットアップ

ExpoのGetting started的なページがあるので、この通りセットアップすれば 5番目の expo start の手順でもうアプリが動く状態になっています。 Simulatorとかのインストールがまだなのであれば実機で確認するのがアプリを入れてQRコードを読み込むだけなのでお手軽です。Expo Clientをインストールしましょう。AndroidiOS両方いけます。

JSX is 何

React Nativeを始めて最初に躓くのがJSXだと思います。こういうやつです。

最初はJSXを「JavaScriptに埋め込めるつよいHTML」ぐらいにしか考えていなかったのですが、このJSXコードはBabelによって関数の呼び出しにトランスパイルされます。

とてもシンプルですね。入れ子になっても基本的にはこの形になると思います。
なんとなくでプロジェクトを作成すると、テンプレ的に入っているJSXやら何やらが急に押し寄せてきて、「なんかよくわからんけど動いてる〜!」という感じになってしまうのですが、ただの関数呼び出しと考えればだいぶハードルは下がると思います。

このあたりの話は、 JSX In Depthに書いてあります。英語ですがコードが多いので雰囲気はつかめるでしょう。 JSXの文法的なところでうまくいかないときはこのドキュメントを読むことで解決することが多いです。

開発環境は何を選ぶ?

Reactの場合、ES Modulesと呼ばれるモジュールシステムを活用したコードを記述する必要があります。
私は普段、JavaScriptは(シンタックスハイライトと簡単補完が効くぐらいの)ほぼ素のVimで書ける程度のJavaScriptしか書きませんが、importやらJSXやらを記述するとなると、素のVimだとかなりのつらみがあります。平成もあと数カ月で終わるというのに、importしたいものを人力で探すという行為はもはや人間がする仕事ではありません。
なので、私はReact NativeでコーディングするときはWebStormを使うようにしました。Vimの環境を汚したくなかったのと、Javaを書くときはIntelliJ IDEAを使っていたためです。プラグインとかを新たに入れなくともデフォルトで補完とかが効いたような気がします。当たり前ですがあると便利です。WebStormは有償ですが、無償のものを選ぶのであればVS Codeとかでも良いと思います。

react-native linkの謎

セットアップ手順にreact-native linkをしているnpmモジュールがありますが、Expoだとnpm installすればだいたいすぐに使えるので、Expoが持っている機能でアプリを作っているうちは特に気にする必要は無いのかなぁと思います。(というより、expoを普通にセットアップした場合react-native コマンドはPATHに居ないですし。。) 逆に言うと、Native Modulesを使いたいときには意識する必要があります。そのときはこのあたりから参照しましょう。

Detaching to ExpoKit - Expo Documentation

画面の作り方

Button よりも TouchableOpacity

Button に良い感じにスタイルを当てたかったのですが(サイズを変えたり画像を入れたり。あとはテキストを小文字にしたかった)あまりうまく行かなかったですね。
どうやらこの Button には結構制約があるらしく、ちょっと凝ったことをするならば TouchableOpacity が推奨されているみたいです。ちょっと込み入ったことをしたときはTouchableOpacity 、そうでないときは Button のシンプルさがマッチします。

React Nativeの画面遷移

画面遷移は react-navigation を使います。 使い方はこのあたりにドキュメントがあります。

例ですがApp.jsが下記のようにデフォルトのまま記述されているとして、分解してゴニョっとやるとすぐに画面遷移が使えるようになります。

元のApp.js

書き換えて画面遷移が出来るようになったもの

React Nativeにおいて画面のコンポネントはScreenで終わる名前にするのが良いらしいです。 App.jsの中に記述されていたコードが、screen/HomeScreen.jsに移動したことがわかると思います。 具体的なソースコードは長くなるので割愛しますが、遷移先の画面を用意すれば画面遷移ができる状態になっています。

SwitchNavigatorやStackNavigatorを使ったときにどのような画面遷移が実現できるかはNavigationPlaygroundというアプリを動作させることでイメージがつかめると思います。 実機確認するときと同じようにQRコードを読ませると動きます。

バックエンド

React NativeでのRESTful APIコール

何かJSONを返すようなAPIを叩きたいときはaxios使うと通信できます。Promiseベース!便利ですね。

READMEにも同じようなものが載ってますがこんな感じです。

Firebaseの利用

Firebaseを使いたいときは、とりあえず npm install firebase をすれば使えるようになります。 react-native-firebaseとかいろいろあってどれを使うべきか迷いますが、今の所firebaseであまり困ってないですね。。

Expoを使ったアプリ開発の場合、実行しているのはNode.jsで動作するJavaScriptでFirebaseのライブラリを動作させるため、参照すべきドキュメントは、ウェブで使ってみるのドキュメントです。

https://firebase.google.com/docs/web/setup

ローカルストレージの利用

バックエンドではないですが、端末にあるローカルのストレージを使うには、 AsyncStorage が使えます。
WebStorageに近いAPIが使えます。値にオブジェクトを突っ込むと壊れるっぽいので、JSON.stringify で雑にJSONシリアライズして雑に setItem してやると雑に良い感じになります。
ただ、考えて使わないとグローバル変数化して頭悪い感じになりそうです。

なんかおかしくなった

Expo(expo startしている方)がおかしそうなとき

expo start するときに、 --clean オプションを付けることでキャッシュをクリアできます。 expo start --clean みたいな感じです。

あとは node_modules を消して npm install し直すとうまく行くことがあります。

Expo Client側が原因っぽいとき

Expo Client側が何かおかしいとき(一般に公開されているものも使えないとか)は、アプリのデータを削除するとうまく行ったりします。

よくわからないとき

シュミレーター開いてたら閉じて(完全に閉じる)リセットしつつ、node_modulesを削除して、コーヒーとか飲んでからもう一度npm install すればなんかよくわからないときもなんとかなります。ならなかったらすみません。

まとめ

たまに赤い画面が出ることもありますが、だいたいググって気合いでどうにかなる感じです。よくわからないときは

             /)
           ///)
          /,.=゙''"/
   /     i f ,.r='"-‐'つ___   まぁなんでも動きゃあいいんだよ!!!
  /      /   
,.-‐'~/⌒  ⌒\
    /   ,i   ,二ニ⊃( ●). (●)\
   /    ノ    il゙フ::::::⌒()⌒::::: \
      ,イ「ト、  ,!,!|     |r┬-|     |
     / iトヾヽ_/ィ"\      `ー'´     /

というマインドでどうにかしますが。 React Nativeみたいな、目の前で画面が組み上がっていくものを作っていくのは楽しいですね。

普段はJavaとかですが、React Native(+ Expo)は新しいものをもっともっと触っていきたいなぁという気持ちにしてくれます。

Java Community ProcessにAssociate Memberとして登録しました。

tomotaka.hatenablog.com

このツイートとリンクの記事を見て、「あ、これ(JCP)って誰でも参加できるんだ」ということを知り、Associate Memberとして登録を行いました!

JCPそのものやメンバシップについては、じゅくちょーさんの記事が詳しいです。 www.sakatakoichi.com www.sakatakoichi.com

Associate Memberになることで、Java Specification Request(JSR)にContributorとして参加することが出来たり*1、EC選挙で投票を行えたりします。
基本的な登録の流れは上に貼り付けたtomotakaさんの記事の通りなのですが、一部「これは...?」と思った部分があったのでそのあたりを書きたいと思います。

1. 現在はManual Signatureのみ(でも中身は電子署名と一緒?)

The Java Community Process(SM) Program - Participation - newMembership

f:id:noko_k:20180811124219p:plain

私が登録したタイミングでは、Manual Signatureにするかどうかのチェックボックスが無く、キャプチャのNOTEに記載があるとおりManual Signatureによる登録プロセスになる模様です。
ただ、SubmitしたところPDFの契約書がメールで届き、それにAcrobat Readerで署名を行い返信する、先程貼り付けたtomotakaさんの記事と同じようなプロセスで登録できました。
FAX送らないといけないのかななどとドキドキしながらメールを待っていましたがあまり気にすることはなかったのかもしれません。

2. 英語の契約書について

完全に私の問題なのですがちゃんとした英語の契約書を書くのが初めてで、 一回目の契約書の送信では記載に誤りがあったために受理されず修正を依頼されてしまいました。

  • Signature: 手書きフォントでの署名(Acrobat ReaderのFill & Signを利用する)
  • Name: 通常のフォントでの名前(通常の記入(編集)で入力する)
  • Title: 役職
  • Date: 署名をした日付(dd/mm/yyyy)

最終的に受理された契約書の記載です。

f:id:noko_k:20180811130910p:plain

修正を依頼されたのはSignatureのところで、SignatureとNameの違いがわからずどちらも同じようにゴシック体で「Noriyuki Kazusawa」と記載したのですが、Signatureは手書き(cursive)のフォントで記載する必要があったようです。
(契約書が添付された)最初に受信したメールをよく見たら、「署名をするときはAcrobat ReaderのFill & Signを使うと良い(意訳)」と記載があったので、ちゃんと読むべきでした。

登録を終えて

Membersに私も名前が載りました!日本人で個人登録している人は2018年7月時点で9人*2らしいのでざっと見ても日本人はだいぶ少ないですね.. JUG経由での参加をする方が多いのでしょうか

The Java Community Process(SM) Program - Participation - JCP Members f:id:noko_k:20180811123656p:plain

Associate Memberの登録に際して、JCP 浜本様には多大なご協力をいただき登録をすることが出来ました。 浜本様には私の契約書の誤りからその後のJCPプロフィールの同期等についても丁寧にご対応していただき感謝しております!

*1:ContributorになるにはPMOとSpec Leadの承認が必要なようなので、誰でもなれるわけでは無さそうです。多分。

*2:https://jcp.org/aboutJava/communityprocess/JCP_Japan_JUG_visit_July2018.pdf

Gradleでファイルの改行コードをCRLFからLFに変換する

コード

// build.gradle
import org.apache.tools.ant.filters.FixCrLfFilter
task convert(type: Copy) {
  from file("CRLFなファイルの置き場所")
  into file("変換後のファイルの置き場所")
  filter(FixCrLfFilter, eol:FixCrLfFilter.CrLf.newInstance("lf"))
}

ANTLRでの例

今回は、ANTLRv4で出力したコード(Windows環境で出力するとCRLFで出てくる)をLFに変換するコードを記述します。

やり方

  1. ANTLRの出力先を一時ディレクトリにする
  2. 一時ディレクトリから、本来出力したいディレクトリにCopyタスクを使ってコピーする

1. ANTLRの出力先を一時ディレクトリにする

2でCopyタスクを利用するとき、コピー元とコピー先が一緒だとうまくいかないので、ANTLRv4の出力先を変更します。

Karaffeの例

   generateGrammarSource {
-    outputDirectory = file("${projectDir}/src/main/java/org/karaffe/compiler/frontend/karaffe/antlrautogenerated")
+    outputDirectory = file("${projectDir}/build/tmp_antlr")
   }

元々は "${projectDir}/src/main/java/org/karaffe/compiler/frontend/karaffe/antlrautogenerated" に出力していたのですが、 "${projectDir}/build/tmp_antlr" に変更しています。

2. 一時ディレクトリから、本来出力したいディレクトリにCopyタスクを使ってコピーする

AntのFixCrLfFilterとCopyタスクを利用して、CRLFからLFに変換します。

task filter(type: Copy, dependsOn: generateGrammarSource) {
  from file("${projectDir}/build/tmp_antlr")
  into file("${projectDir}/src/main/java/org/karaffe/compiler/frontend/karaffe/antlrautogenerated")
  filter(FixCrLfFilter, eol:FixCrLfFilter.CrLf.newInstance("lf"))
}

compileJava.dependsOn filter

一時ディレクトリに置かれたファイルの改行コードを変換しながら移動するfilterタスクを実装しました。
このfilterタスクは、ANTLRが生成したファイルがあることが前提となるので、 dependsOnANTLRプラグインのタスク generateGrammarSource を設定しています。
さらに、この移動したファイルは compileJava で利用するため、 compileJavaの依存タスクとしてfilterタスクを追加しています。
これにより、
generateGrammarSource -> filter -> compileJava の順番でタスクが流れていきます。

ANTLR以外で使う場合でも、dependsOnとかを修正すれば使えるかなと。