年末開発合宿~「React Native News App」に挑戦~

## 位置付け
忘れやすい性格なので2021年末に何をしたか備忘録のため、また後学のために残しておきます。

## 成果物の概要
News API (https://newsapi.org/) からニュースを取得するアプリ

#### News一覧
![IMG_9836.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686487/57daeafb-7754-a4ff-7d91-7516e93281f1.png)
#### クリップ機能
![IMG_9837.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686487/1ce69956-0371-79b4-fb89-543c9f603c51.png)



## 開発の動機
同期エンジニアと開発をしたいというモチベーションがあって誘いました。
研修で一緒に開発するのが楽しかったし、成長している同期エンジニアから学びたいという気持ちがあったためです。
会社で開発の時間が限られている(保守・運用の時間が一定程度ある)ので、作りたいものを作るというエンジニアの原点に立ち帰りたかったというのもあります。
また、ネイティブアプリ開発への挑戦を以前からしたいと思っていたので、気になっていたReact Nativeを開発言語としました。

## 開発環境
- Docker for Mac Version 3.3.3(64133)
- Node: v12.7.0
- Expo: v35.0.0
- Expo CLI: v3.8.0

## 筆者のスキルレベル
- 職業: IT エンジニア (1年目)
- PHP、JavaScript
- 仕事内容 : 不具合改修がメイン
- React Nativeがクロスプラットフォームであることは知ってる。。。
- コンポーネント指向？あぁ、小さく分けて組み合わせる開発する考え方ね。。。
- Node.js? あぁ、サーバーサイド開発のためのJS開発環境的なやつね。。。
- Expo? 何かの博覧会？


以下参照。
https://github.com/tinaba96/fnews/blob/teru/README.md


## 開発手順
基本的には下記のUdemy講座を参考に開発を行います。
> [React Native入門：ニュースアプリを作りながら覚えよう/Hooks対応版
](https://bizmatesjp.udemy.com/course/react-native-first-step/learn/lecture/)

上記Udemy講座ではローカル環境構築を行なっていますが、僕はDocker上に構築しました。
DockerでのReact Native開発は、実機での検証は行うことができるのですが、Xcode simulatorを使うことができないので、おすすめはしません。また、後述しますが、Docker内部ネットワークから外のネットワークに対して通信できるのですが、外から内への通信ができなくてハマりました。(`runコマンドと一緒に-pを指定することで解決`)

というわけで、次回React Nativeで何らかの開発をする際にはローカルで環境構築を行いたいと思います。

> Dockerでsimulatorは使えないらしい。
[DockerでReact Nativeの開発環境を作って、iOS Simulatorを起動したいです。](https://teratail.com/questions/360034)

## 疑問を解消
まずは、以下、開発前・開発中に疑問に思ったことをつらつらと自分なりに噛み砕いていきます。

####  Node.jsって何？何で必要なの？
一言で言うと、サーバサイドのJSの実行環境。従来は、JSはブラウザ(この場合、ブラウザがJSの実行環境を兼ねていた)で実行するプログラミング言語だったが、サーバーサイドでもJS書けたら便利だよねっていう背景もあって開発されたとのこと。


以下、Node.jsの特徴。
- シングルスレッドで非同期処理を実行から、リアルタイムwebと相性が良い言語フレームワーク
- Webサーバとして利用できる
- Webアプリ、スマホアプリの開発ができる
- 多数の同時接続を管理できるらしい。

> 
Node.js はスケーラブルなネットワークアプリケーションを構築するために設計された非同期型のイベント駆動の JavaScript 環境
https://nodejs.org/ja/about/

なぜ必要か？に関してはReact Native関係のパッケージ類がNode.jsのパッケージ管理ツール「npm」で管理されているから。



> [Node.jsとはなにか？なぜみんな使っているのか？](https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb)
[Node.jsとは？できること5つやNode.jsを学ぶ方法をご紹介！](https://www.acrovision.jp/career/?p=2934)
[【図解】1から学ぶ JavaScript の 非同期処理 ](https://qiita.com/ryosuketter/items/dd467f827c1b93a74d76)

---

#### 並行処理、並列処理の違い
いつもどっちがどっちかを忘れてしまうので、もう忘れないために残します。
並行処理は、1人の人間がAという処理をしながらBという処理もすること。
並列処理は、複数の人間が複数の処理をすること。

---
#### npmとは？yarn?
npmは、JSの公式パッケージマネージャ。
yarnは、JSの非公式パッケージマネージャ。

今はあまり変わらないそう。。。

> [【JS】yarnの長所とyarnからnpmに戻ってきた理由](https://jsnotice.com/posts/2020-09-02/index.html#npm%E3%81%A8yarn%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

---
#### バンドラとは？
複数のモジュールの依存会計を解決して1つにまとめたもの。
JSは、開発においてそれぞれの機能ごとにファイルを切り分けて開発する。しかし、ファイルが多くなると、ブラウザで表示する際にはリクエストを行う回数が多くなる。リクエストが多くなることは、表示速度の遅延を意味する。そこで、必要最小限のリクエストで済むようにまとめる必要がある。

モジュールを１つにまとめることができるwebpackはめっちゃ便利ってことがわかった。(知識不足だけど)

> [モジュールバンドラーはなぜモダンなフロントエンドの開発に必要なのか？](https://note.com/billion_dollars/n/n596fecfdeb2e)
> [webpack 入門ハンズオン - 最小アプリを実際に作成してモジュールバンドラの利点を理解する](https://qiita.com/TsutomuNakamura/items/70dd97dcbdc02bef2706)

---
#### Expoって何？
React Nativeは、iosやandroidの差分を吸収して両方で動作するアプリを開発できる言語。Expoは、さらにそのReact Nativeを包み込んで、簡単にネイティブアプリを開発できるツール。

---
#### ios Simulatorが動かないのは何故？
XcodeからSimulatorを起動してもSimulatorを立ち上げることができなかった。
これは、Dockerコンテナの中にXcodeが入っていないから。

> [DockerでReact Nativeの開発環境を作って、iOS Simulatorを起動したいです。](https://teratail.com/questions/360034)

---
#### AsyncStorageとは？
React Nativeにおけるデータを永続的に保存するライブラリ。

データを永続的に保存するには、以下の方法があるが、簡易的に実現するためにAsyncStorageを利用する。
- サーバに保存
- ローカル領域のストレージに保存
- SQLiteなどのアプリケーション内DB

 
> https://reactnative.dev/docs/asyncstorage

---
#### hookとは？
Classコンポーネントを使用せずとも、Functionコンポーネントで、状態管理などができるようにしたもの。
フック (hook) は React 16.8 で追加された新機能で、React Native は バージョン0.59以降でフックをサポートしている。

> [5分でわかるReact Hooks
](https://qiita.com/Mitsuzara/items/98d1bc4a83265a764084)

---

#### スプレッド演算子

> スプレッド構文は、オブジェクトや配列のすべての要素を何らかのリストに入れる必要がある場合に使用することができます。
[スプレッド構文
](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)

```
function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];
console.log(sum(...numbers));

let newNumber = 12;
numberStore = [...numbers, newNumber];
console.log(numberStore)

//実行結果
> 6
> Array [1, 2, 3, 12]

```

## ハマったこと
#### expo startしてもhttp://Local-IP:19002/ にアクセスできない。
`expo start`すると、expo サーバが立ち上がるが、http://Local-IP:19002/ にアクセスできなかった。

コンテナ内から以下で疎通確認しても通っているので、何故だろうと思っていたが、よくよく考えてみたら当たり前の話。
```
$ nc -vz localhost 19002
Connection to localhost port 19002 [tcp/*] succeeded!
```
コンテナ内でサーバが立ち上がっているので、そこにブラウザでアクセスするには、外部ネットワークから見えるように公開されている必要がある。

これは、dockerのコンテナネットワーク外(ホスト側のネットワーク)からdockerのコンテナ内ネットワークに通信するには、ポート公開をする必要があることが原因。
> 
https://stackoverflow.com/questions/59638451/metro-bundler-with-expo-dockerized-app-is-not-working
-p, --publish=[]      コンテナのポートをホスト側に公開
https://docs.docker.jp/compose/reference/run.html


## React Native開発で知っておくこと
- Component指向

何を作るにしてもComponentを作って組み合わせていく。
あらかじめComponentをドキュメントを見てタグの使い方を学ぶ感じ。
https://docs.expo.dev/versions/v44.0.0/react-native/text/

- hook
    - useState
    - useEffect

Function コンポーネント(class コンポーネントではなく)で開発するには、hookが必要らしい。classを書かなくても状態管理等を行うことができる
> [フックの導入](https://ja.reactjs.org/docs/hooks-intro.html)

- axios
    - 非同期通信をする際のライブラリ
- React Navigation
    - 画面遷移の際に使用するライブラリ
- Redux
    - 状態を管理するライブラリ
- ActionをDispatchしてReducerを利用してStoreに保存する。
    - 永続化。メモリではなくスマホのストレージに保存する


## React Nativeで開発してみて感じたこと
- 実際にシステムを運用するとなると、どうしても改修をする必要性が出てくるが、その際にコンポーネント指向で機能毎にファイルが切り分けされていると、改修が楽になりそうだなぁと思いました。(今回実際にやったわけではないが、普段の業務では改修のたびに1000行くらいのコードを読む必要があるので超疲れます。。。)
- 思ったより簡単にスマホのアプリが開発できた(ExpoとUdemyの講座がすごい)ので、参入のハードルは低いと感じました。
あと、ドキュメントが読みやすく、しっかり手が入っているなと感じました。
- 実機での確認(Docker上に構築していたためSimulatorが使えなかった)となりましたが、ホットリロード(ソースコードを保存するたびに自動でリロードする)機能はPHPでのWeb開発と同様にすぐ反映されるので開発しやすかったです。


次回React Nativeの開発をするときは、Docker上に構築せずローカルで環境を整えて開発したいと思います。


## Apple Storeに申請を出してみた(2021年1月5日 追記)

Apple Storeに申請を出すまでに結構いろんな工程を踏む必要があった。

### 簡単な手順
```
//ビルドしてipaファイルをダウンロードする
expo build:ios --release-channel production

//その後、Transporterというアプリを利用してApp Store Connectにバリする。

//その後、アプリの説明やらスクリーンショットやら、プライバシーポリシーやらを設定
```


そして申請後、数時間後にRejectされた内容がこちら↓↓
> Guideline 4.2.2 - Design - Minimum Functionality

> We noticed that your app only includes links, images, or content aggregated from the Internet with limited or no native iOS functionality. Although this content may be curated from the web specifically for your users, since it does not sufficiently differ from a mobile web browsing experience, it is not appropriate for the App Store.

> Next Steps

> We encourage you to review your app concept and work towards creating an app that offers customers an engaging and lasting experience that also meets the App Store’s high expectations for quality and functionality.

> Apple Developer includes a variety of design and development resources. Download iOS templates from Apple UI Design Resources, learn more about crafting intuitive, well-designed apps with the Design Video collection, and review the iOS Human Interface Guidelines for best practices to follow when designing apps for the App Store.


つまり、Webアプリと何が違うの？ということ。

じゃあ、ネイティブアプリっぽい機能をつけて再挑戦。

### 再申請１回目 ~ 共有機能を追加
![IMG_9799.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686487/523d11d5-2af5-5ccd-2228-92b3f6ee74eb.jpeg)


見事承認された。
しかし、実際にApple Storeでインストールして確認してみると、前のバージョンのまま(初回申請時と同じ)再申請が行われており、前のバージョンのまま承認されていたことがわかった。。。ww
まぁ承認されたからよしとしよう。

↓これを参考に再度やったら上手くいった。
> [React Native ExpoのiOSアプリをバージョンアップする手順](https://kabueye.com/articles/react-native-expo-update-app)

バージョンの付け方は以下を参照。
>https://www.lyzon.co.jp/blog/2019/20191017_how_to_attach_version_name/

輸出コンプライアンスについて以下を参照。
> [iOSアプリ提出の輸出コンプライアンスで、通信にHTTPSを使っているだけの場合の解釈](https://qiita.com/osamu1203/items/35df25d93e9d12b11222)