TL;DR
- React Native を触ったことがなかったので、Expo のチュートリアルを読みながらキャッチアップした。
- React Native の基本コンポーネントと、ジェスチャー、アニメーション、ナビゲーション、画像、メディアライブラリを扱うライブラリの API をまとめた。
背景
React Native を触ったことがなかったので、Expo の公式チュートリアルと Zenn の解説を読みながら、Expo でアプリを作った。
検証
React Native
View は UI のレイアウトを組むためのコンテナで、子要素を Flexbox で配置したりスタイルを当てたりできる。DOM の <div> に近い。Text は文字列を表示するコンポーネントで、フォントサイズや色などを指定でき、ネストすれば部分的にスタイルを変えられる。スタイルは StyleSheet.create() で CSS のように定義する。
Pressable は、タップや長押しなどのプレス操作を検出する汎用的なコンポーネントで、押している間のスタイル変更など、操作に応じた見た目を細かく制御できる。Button より柔軟である。Modal は、ダイアログのように現在の画面の上に一時的にコンテンツを表示する。表示・非表示は visible、アニメーションは animationType で指定する。
FlatList は、大量のデータをスクロールで効率よく表示するコンポーネントである。画面に見えている要素だけを描画する仮想化(virtualization)で、メモリ使用量とパフォーマンスを最適化する。ヘッダ、フッタ、区切り線、Pull to Refresh にも対応している。Platform は、Platform.OS のように実行中のプラットフォームを調べるモジュールである。
React Native Gesture Handler
React Native Gesture Handler はタッチジェスチャーを扱うライブラリである。ジェスチャーを認識させるには、アプリの最上位かジェスチャーを扱う View の階層のルートに GestureHandlerRootView を置き、対象を GestureDetector で包む。
Gesture.Tap() はタップを定義するビルダ関数で、numberOfTaps() で必要なタップ回数を、onStart() で認識されたときの処理を指定する。Gesture.Pan() はドラッグやスワイプを定義し、onChange() のコールバックは指が動くたびに、移動量などを含むイベントを受け取って呼ばれる。
React Native Reanimated
React Native Reanimated はアニメーションのライブラリである。useSharedValue は、アニメーションの状態を持ち、JavaScript スレッドと UI スレッドで共有できる値を作るフックである。この値の変更はリアクティブで、参照しているスタイルの再計算を自動で引き起こす。
useAnimatedStyle は、共有値の変化に応じてスタイルを計算するフックである。処理は UI スレッドで実行されるので、アニメーションが速い。返したスタイルを <Animated.View> や <Animated.Image> の style に渡すと、アニメーションが適用される。withSpring は、sharedValue.value = withSpring(目標値) のように書き、共有値をばねのような動きで変化させる。
画像のキャプチャ
react-native-view-shot の captureRef() は、useRef で取った <View> とその子要素を、画像として非同期でキャプチャする。
dom-to-image は React Native 固有のライブラリではなく、ブラウザ環境で動く。toJpeg() は DOM ノードを受け取り、その見た目を JPEG に変換して、Base64 でエンコードしたデータ URI を返す。
Expo のライブラリ
Expo Router は、React Navigation をもとに Expo 向けに拡張したモジュールである。Tabs は React Navigation の Bottom Tabs Navigator を包んだもので、下部のタブをタップして画面を切り替える。各タブの画面は Tabs.Screen で指定する。Stack は Native Stack Navigator を包んだもので、画面を積み重ねて遷移するので、ユーザは画面を進んだり戻ったりできる。各画面は Stack.Screen で定義する。Link は画面間をリンクで移動するコンポーネントで、DOM の <a> にあたる。
Expo Image の Image は画像を表示するコンポーネントで、React Native の同名のコンポーネントより速い。source に渡すデータの型は ImageSource である。Expo Vector Icons は react-native-vector-icons をもとにしていて、同じ API を持つ。Ionicons や MaterialIcons で、Ionicons や Material Icons のアイコンを使える。
Expo ImagePicker の launchImageLibraryAsync(options) は、端末のメディアライブラリを開いて画像や動画を選ばせ、選ばれたファイルのローカル URI や幅、高さなどを返す。Expo MediaLibrary の usePermissions() は、メディアライブラリへのアクセス許可の状態と、許可を求める関数を返す React Hooks である。saveToLibraryAsync() は、ローカルファイルの URI を受け取ってメディアライブラリに保存する。
Expo StatusBar の StatusBar は、画面上端のステータスバーの文字色、背景色、表示・非表示、半透明などを設定する。Expo SplashScreen は、明示的に隠すまでスプラッシュスクリーンを表示し続けるためのモジュールである。
考察
Expo Router は使ったことがない。React Navigation のドキュメントを見る限り宣言的ではないので、扱いやすく包んでいるのだろうか。