TL;TR
-
Platform.OS
の値が常にios
になってしまった - 原因は初歩的なタイプミスだった
- コミットの粒度はなるべく小さくしよう
何が起こったか
ざっくり説明するとReactNative
製アプリをAndroidで動かした時に、iOSでしか表示されないUIが表示されていました。
下記のようにPlatform.OS
を表示させてみると、出力されるのはios
。
なぜかOSの種類に関わらずiosとして扱われてしまっているようでした。
import { Platform } from 'react-native';
console.log('os : ', Platform.OS); // --> "os : ios" と出力される・・・
react-native
の不具合ならもっとIssueで大々的に騒がれてそうだけど、そんな気配もない。
となると何らかのバグなのだが、Platform.OSの値が必ずiosになってしまうってどんな状況やねん・・・
と思いながら直近のコミットを細かく見ていくと、
import { Platform } from 'react-native';
if(Platform.OS = "ios") {
// iOS限定の処理をつらつらと
}
ああああああああ!!!!
Platform.OS = "ios"
って書いてるうぅぅぅ!!!!
この処理以降、Platform.OS
を参照しても代入されたios
が取れてしまうわけです。
補足
結果的に比較演算子のタイプミスだったわけですが、そもそもこの書き方でif分岐がどうなるかを解説します。
if...else - JavaScript | MDNによると下記のような記述があります。
条件式の中での代入
代入はコードを眺めたときに等式と混同される可能性があるの?で、条件式の中で単純な代入を使わないほうが望ましいです。たとえば、次のコードを使わないでください。
if (x = y) {
/* do the right thing */
}
なるほど、使わない方がいいけど文法的にはアリみたいです。
ちなみにこの場合、ifの評価は代入された後の変数で行うらしく、下記のような結果になります。
var a = 0;
if(a){
// 通らない
}
else {
// 通る
}
if(a = 10){
// 通る
}
else {
// 通らない
}
if(a = undefined){
// 通らない
}
else {
// 通る
}
つまり先のタイプミスをした
if(Platform.OS = "ios") {
// iOS限定の処理をつらつらと
}
は評価としてはtrueになります。
まとめ
結果的に原因は初歩的なタイプミスだったわけです。
気付いてみればなんてことないんですが、大規模なコミットに埋もれていたため見落としてしまいました。
テストで発見できればよかったのですが、Android端末で問題となった処理を行った後でないとPlatform.OS
が書き換わらないのですり抜けてしまったようです。
教訓としては、コミットの粒度を小さくしてタイプミスを発見できるようにする。です。