React Nativeにおけるプラットフォームごとのコード分割

React Native

タイミング ~どんな時にコード分割するべきか?~

1.スタイル

例えばTextInputを使う場合、iOSAndroidではかなりあてるスタイルが異なります。

TextInputはiOSではheightの設定が必要だったり背景色やボーダーが無いとフォームが解りづらいので設定する必要があります。

Androidの方は元から適切なPaddingや高さ、入力フォームがわかるように下線が付いていたりしますので背景色やボーダーを追加する必要はありません。

https://saburesan.hatenablog.com/entry/2017/04/01/134836

2.ロジック

RNが提供するAlert.prompt()など、iOS only, Android onlyな処理。プッシュ通知などネイティブ依存の処理。

3.props

RNが提供するAlertのAlertType propsなど、iOS only, Android onlyなprops。

手法 ~どうやってコード分割するべきか?~

前述したコード分割タイミング「スタイル」「ロジック」「props」で手法が分けられる。

1.スタイル

RNが提供する「Platform.select()」メソッドを利用する。

const styles = StyleSheet.create({
  container: {
    flex: 1,
    ...Platform.select({
      ios: {
        backgroundColor: 'red'
      },
      android: {
        backgroundColor: 'green'
      },
      default: {
        // other platforms, web for example
        backgroundColor: 'blue'
      }
    })
  }
});

2.ロジック

RNが提供する「拡張子による動的import」を利用する。RNは、「XXX.ios.js」「XXX.android.js」という規則で命名されたファイルを、その時のプラットフォームを見て自動でimportするファイルを選んでくれる。

つまり、

import xxx from "./XXX";

だった場合、iOSであれば「XXX.ios.js」、Androidであれば「XXX.android.js」を自動で選んでimportする。(expoでも同じようなことができたよね)

この機能を利用し、iOS only・Android onlyな処理をファイルに抽出し、それぞれ「XXX.ios.js」「XXX.android.js」と命名する。

ただ、個人的にほんの数行のロジック分割であれば、1.スタイルのPlatform.select()で十分だと思う。

「拡張子による動的import」は、プラットフォームにより処理が変わっちゃうという関心事をファイルに分離することで、呼び出し元ではその関心事を気にしないこと (要はカプセル化)がメリットであり目的であるが、

数行のロジックをファイルに分離しだしたら、可読性ガク下がりで結果的に全体のコード品質は下がるよねって話。

3.props

これに関しては、特にコード分割は必要ないのではないか。

例えば、AlertのAlertType propsはiOS onlyのpropsだが、Android環境では無視されるだけなんで特に対処する必要はないと思う。ただ、開発者が「Android環境では無視される」という事実さえ認識していればよい。

その他Tips

RNが提供する「Platform.OS」は、プラットフォームが文字列として格納されている。

const styles = StyleSheet.create({
  height: Platform.OS === 'ios' ? 200 : 100
});

また、各プラットフォームのバージョンを取得できる。参考

参考文献

ReactNativeでiOS, Androidに最適化したUIを構成するには

React Nativeでプラットフォームごとの処理を書く

【公式】Platform Specific Code

コメント