さてはて、ネタがある時には書いておかないとね。
真面目に開発する初めてのアプリとして選ばれたのは、RNでした。
はい。一部の界隈で好まれているクロスプラットフォームのアプリ開発言語、ReactNativeさんです。
近くにReactNative推しの人物が居たもので、彼の協力も受けながらこのアプリを開発していったわけです。

知ってのごとく、私はファミマでバイト中ですが、

どーしても記憶が苦手!

なんですわ。
どうしたもんかねぇ。
その筆頭が揚げ物なわけですが、どれも揚げる時間もバラバラだったり一緒だったり。
いつも同じシフトの人はなんと4種同時揚げとかもこなすプレーヤーなのでどうしてもここはなんとかしないと作業のバランスが取れない。
どうしたもんかねぇ。
表が複雑すぎて、自分が記憶するには時間が足りないよ...や、時間が足りても俺のキャパが足りねぇよ...

という致命的な理由で開発することにしたのでした。


いやま、

足りない能力はある能力で代用するしかないからね!!!!!ね!?けっして記憶を諦めたわけじゃないからね!!!

というわけで製作していったのです。

作るにおいて重要としたのは次の要素。
1 一部だけでもファミマのposレジと統一した操作感を
2 進捗の管理がしやすいように
3 データの追加がしやすいように
4 揚げ物作業時間にそこそこ開いたまま放置することになるので画面が消えないように
5 同じ理由で広告を設置するとおかねかせぎに有効そうなので設置

というわけで、使用しているモジュール要素を紹介。
react
react-native
react-native-elements
react-native-router-flux
react-native-swipeable
native-base
react-native-vector-icons/AntDesign
expo
expo-ads-admob
これが実質的な初めてのreactnativeアプリ開発となりました。
まぁ完成を見てくださいまし。



Screenshot


Screenshot

まずルーティングなのですが....元々NativeBaseやReact-navigationやを使用しようとしていたのですが何故かエラーで動作せず(原因がわからない&どんなエラーだったかももはや覚えてないから多分今なら使えるんじゃないかと)。色々苦労してReact-native-elementsとreact-native-router-flexに到達したという。
以下便利だったこと、覚えておいたほうがいいメモ。


1 何かと画面を更新させたい時はダミーでもいいのでstateを用意してそれを更新させるアクションを実行させればよい。無理にstateにする必要はない。 →stateってのは要するに画面描画をさせるためのツールでしかない。
(あまり推奨されないかもしれないから信用はしないでネ)


2 変数の内部に結構適当にJSX(htmlみたいなもの)を配置できてしまう。これは楽だが逆にどこからがJSXでどこまでがjsなのかが個人的にわかりにくく頭の中で常に完成図を組み立てながらしなければならないようだ。
    const Cards = [];
    for(var i=0; i<商品.length; i=i+2){
      if((i+1) < 商品.length){
        switch(this.ifSelector(i)){
          case 1:
            Cards.push(
              <View style={styles.縦}>
                {this.makeItem(i)}
                {this.makeItem(i+1)}
              </View>
            );
          break;
          case 2:
            Cards.push(
              <View style={styles.縦}>
                {this.makeItem(i)}
              </View>
            );
          break;
          case 3:
            Cards.push(
              <View style={styles.縦}>
                {this.makeItem(i+1)}
              </View>
            );
          break;
          default:
          break;
        }
      }
      else{
        switch(this.ifSelector2(i)){
          case 1:
            Cards.push(
              <View style={styles.縦}>
                {this.makeItem(i)}
              </View>
            );
          break;
          default:
          break;
        }
      }
    }
これなんて特にわかりにくいと思う。実体はトップのアイテムを左右に配置している処理なのだが、配列変数Cardsの中身に<View>をループでガンガンプッシュしているのだ。
ifselectorは別の関数で処理選別をしているので無視してもらいたい。
この<View>の中身にthis.makeItemとあるが、これはJSXではなくjsだ。makeItemという自作関数を実行するようになっているので、私の頭は「表示する領域に実行する領域があるとはどういうことだ」となるのだ.....
届いたAmazonの箱の中身を見たら「Amazonの商品が入ってます」と書かれた紙だけが入ってた、ような雰囲気がした(例えがヘタクソ.....)この感じ、わかる人いるかなぁ....
とはいえ、この万能さ柔軟さがReactNativeの持ち味のようにも感じる。実際はそのAmazonの紙を見て配送業者の人が詰めこんで、の過程を成して商品が箱に入って届くように。
とはいえ私はこういうのは大好きだ。苦手ではあるけども。

話を戻そう、jsとJSXの境目だが、実行結果の内容がjsxというイメージを浮かべている。コンソールにprintfをするような、alertでjsポップアップを生成するような、実行結果の内容。returnの中身がJSXになっているので、reactnativeは必ずdefaultのクラスの中のrender関数の中のreturnになり、ただ表示されるだけでも複雑だ。いやま、他の言語もあまり触らないからわからんけども。


3 admobをしたければexpoにadmobがあるから、表示させるクラスにインポート
import { AdMobBanner } from 'expo-ads-admob';
してrender/returnに追加
<AdMobBanner
bannerSize="fullBanner"
adUnitID="自分のadmobユニットID" // Test ID, Replace with your-admob-unit-id
onDidFailToReceiveAdWithError={this.bannerError}
style={{height: 60}}/>
すればいいだけ。

とはいかないようだ。ここが苦労したのだが、app.jsonの方にも追記が必要なようで、
"extra": {
"admob": {
"android": "アプリID"
}
},
を追加した。iOS版も作るならそれも下に追加していけばよい。あれ?iOSとAndroid両方の時ユニットIDはどうなるんだろう....まぁいいか()
あと、これを追加してもadmob側の認証が終わるまでは広告が表示されないのでそもそもミスがある可能性と進捗待ちが実にわかりづらい。それもexpoのテストでは動作しているのにビルドした方だと広告が表示されないなんてよくあることだ。これも待機が必要かもしれない。


4 要素を中央配置したいなら面倒なcssなど諦めて空の<View>とflexを乱用すれば楽ということに気がついた。
<View style={{flex:1}}>
<View style={{flex:1}}></View>
<Text style={{flex:1,color:this.state.ヘッダーカラー}}>
{this.state.ヘッダーテキスト}
</Text>
<View style={{flex:1}}></View>
</View>
これは中央のTextを、最上位のViewから見て中央に配置したかった時のものだ。本来ならstyleでmarginなどセットするのだが、面倒なので空のViewを上下に挟み、全てをflex:1とするのだ。これで最上位Viewから見て要素は三っつが均等配置されている状況になり結果テキスト要素は中央に配置される。
このViewは縦にも横にもstyleで指定することで並べられるようになるので空Viewで手軽にUI配置の効率アップだ!


5 タッチにしたければその範囲をTouchableNativeFeedbackで囲んでしまえばおけ。ただしonPressの中身は関数ベタ書きではなくアロー関数。
これ、そこそこハマったんだけれども、OnPressの中身がアロー関数じゃないとGUI生成時にその関数が自動で実行されちゃう。
onPress={() =>this.CountItem(item)}
アロー関数ってのはこの中身の() => 関数 ってやつ。自分もよくわかってないけれど関数でエラーが出た時にこれに変更したらエラー出なくなったりするから便利だなぁと思いながら使わせてもらっている.....理解が中途半端でわるいな!!!
なんとなく、直書き→画面生成時に同時に実行されちゃう。アロー関数経由→タッチ時までは実行されない というイメージになってるけど多分間違ってはないと思う。

6 変数だけ別ファイルにしたい時はexport default 変数名=内容!インポートするときはimport 変数名 from 'ファイルの場所';
ここもよくわかってないので苦労したが、とりあえずこうすれば完成ビルドでもちゃんと変数がロードされるようで。というか。「テスト実行で変数読み込まれるのにアプリに出力したら変数読み込まれない」とかいうクソ事象が発生してたからもうねぇ....苦労したよ....


ReactNative使ってみての感想

ぶっちゃけいって、マジで便利。
OTAがな。
このアプリって、ファミマのアプリなんで毎週メニューの内容が変化します。そのため、どこかのサーバーにデータを送信してそれを読んでもらって、ファイルだけを更新させてアプリ更新はしたくないと思っていたのですが。まさかexpoに適当に何も考えずにアプリ本体を投げるだけでいいとは。
外部から読み込むスクリプトとか面倒そうだなぁって思ってたけれどぜんぶexpoに投げるだけでいいのは楽ですね。代わりといってはなんですがデータの更新に再起動が必須なことが....
まぁ他にも色々触って、違いを感じていきたいかなぁっって感じですね。
ただ、これからもアプリはReactNativeで作っていく予定です。はい。w