React Native 1年間振り返ってよかったと思える地味なTipsまとめ

こんにちは。
気づいたらアドベントカレンダー当日に。。

日々の開発の中で、もっと早くこうしておけばよかった。。ということを1年前からの分、振り返ってみようと思います。


# Apiリクエストの内容を ChromeDeveloperToolで確認できるようにする

request内容,response内容を ChromeDeveloperToolのnetworkタブで見れるように。
https://github.com/jhen0409/react-native-debugger/blob/master/docs/network-inspect-of-chrome-devtools.md

独自にlog出したりしてたのですが、足りないheader情報など見るために使い始めました。
charles使ったりしていた時期もありますが、はるかに楽なので今はだいたいのプロジェクトで開発ビルドでは使っています。
https://www.charlesproxy.com/

```
global.XMLHttpRequest = global.originalXMLHttpRequest
  ? global.originalXMLHttpRequest
  : global.XMLHttpRequest
global.FormData = global.originalFormData
  ? global.originalFormData
  : global.FormData

fetch // Ensure to get the lazy property

if (window.__FETCH_SUPPORT__) {
  // it's RNDebugger only to have
  window.__FETCH_SUPPORT__.blob = false
} else {
  /*
   * Set __FETCH_SUPPORT__ to false is just work for `fetch`.
   * If you're using another way you can just use the native Blob and remove the `else` statement
   */
  global.Blob = global.originalBlob ? global.originalBlob : global.Blob
  global.FileReader = global.originalFileReader
    ? global.originalFileReader
    : global.FileReader
}
```

# react-navigation をreduxから外す
1年程前には、react-navigationはreduxに繋げて、action から NavigationActionをdispatchする、みたいなことをやっていたのですが、
今では外しています。

https://reactnavigation.org/docs/en/redux-integration.html

>Warning: in the next major version of React Navigation, to be released in Fall 2018, we will no longer provide any information about how to integrate with Redux and it may cease to work

とのことで、情報も更新されなくなるよう。

代替として、下記のNavigationService.jsにあるようにrefを取り回して使っているのですが、redux導入周りで面倒がなくなったのと、actionのログがnavigateばっかりになって見にくくなることもなくなったので、もっと早く外しておけばよかったと思いました。
https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html

# Singletonなクラス
状態をreduxのstate以外で管理していいか、みたいな思想の問題はあるのですが、見通しを考えると使った方が楽なケースもあるかと思い始めました。

たとえばApiの接続時のaccessTokenも認証したあとにreduxのstateに入れるのが一般的かと思うのですが、
accessTokenを引き回すのにうんざりしはじめ、今はApiServiceクラスみたいなものにまとめてしまっていたりします
こんな感じのイメージ

```js

class ApiService {
  private accessToken: string | undefined;

  constructor () {
    // 略
  }

  private setAccessToken ( accessToken ) {
    this.accessToken = accessToken;
  }

  private fetch (uri, options) {
    // fetchやaxiosでいい感じに。
　　　　　　　　return fetch(uri, options);
  }
  
  private fetchWithAccessToken (uri, options) {
    const optionsWithToken = {
      header: { token : this.accessToken },
      ...options
    }
   
    return  this.fetch(uri, optionsWithToken)
  }
　　　
  public getSomeData () {
   return this.fetchWithAccessToken
  }
}

export default ApiService()
```

アクセストークンくらいだとそこまでですが、適宜tokenをリフレッシュしたりするといったこともApiService側にまとめてしまえると、action/reducer側でやらないといけないことが減るので楽になった気がします。


ES6以降のSingletonクラスのexportは下記などを参考にどうぞ
https://qiita.com/hkusu/items/d9ac2bd135e9e579e018
https://qiita.com/NeGI1009/items/f8b17d856a4b15b1ecbc

# reduxは、ducks style & redux-actionsを使って、ファイル数、記述量を減らす
redux周りのファイルが増えすぎてうんざりしたので、1機能 1ファイルにまとめています。
https://medium.com/@scbarrus/the-ducks-file-structure-for-redux-d63c41b7035c

また、state書き換えるだけ、みたいなものも多いので、redux-actionsのcreateActionも使うようにしています


# 無理しないでType Scriptを使う
jsで作り始めたプロジェクトがあったりもしたため、去年は全くTypeScriptを使っていませんでした。
部分的にPropsTypesやflowを導入したこともあったのですが、あまりはまらず、なんだかんだjsのままのプロジェクトも多い状況でした。

が、vscodeにエディタを変えたことと、決め手としてbabel 7が後押しとなり、今ではTypeScript化を進めています。
とはいえ、一気に昔からのプロジェクトも、、となると辛いので、↓の感じで使っています。

・ReactNativeのversionアップ(0.57以上)のタイミングに合わせて導入
・とりあえず拡張子を変えて、エラーも目を瞑る。
・触ったところから順次型情報を増やしていく (時間なかったり、難しいところはanyでやり過ごす。何もないよりはまし)

あとは、、reduxとconnectしているcomponentsなんかは、ReturnTypeやtypeofを使って、個別のStateの型書くのを減らしたり。。
ただこの辺り、もっといいやり方あれば知りたいです。。

```js
interface Props
  extends ReturnType<typeof mapStateToProps>,
    ReturnType<typeof mapDispatchToProps> {
  navigation: NavigationScreenProp<NavigationState, null>;
  articleId: number;
}

interface State {
  articleId: number;
}

class ArticleDetail extends React.Component<Props, State> {
}

```

# react-native-fcmをやめ react-native-firebaseに移行
依存関係の問題とかもあり、react-native-firebase入れ切るまでは気が重いですが、一度入れてしまえば分析も通知もバナー広告も全部できるので、ほぼ全てのプロジェクトでreact-native-firebaseを導入しています。
通知周りだけreact-native-fcmやreact-native-push-notification使っていたところもあったのですが、それもすべてやめました。


# Expo使う
↑にある通りreact-native-firebaseを使っていたり、結構ブリッジのモジュールもいれていたので使っていなかったのですが、
やっぱりビルドでこけるとかがないので楽でいいですね。

導入の際のメモをそのまま

>Expoでできるか確認
>
>・local通知 / push通知
>https://docs.expo.io/versions/latest/sdk/notifications
>
>・share
>https://docs.expo.io/versions/latest/react-native/share
>
>・take screen shot async
>https://docs.expo.io/versions/latest/sdk/take-snapshot-async#__next
>
>
>・victory native
>https://github.com/expo/examples/tree/master/with-victory-native>
>
>・admob
>https://docs.expo.io/versions/latest/sdk/admob
>
>・カレンダー
>https://github.com/expo/examples/tree/master/with-react-native-calendars
>
>・iap
>ない
>
>・レビューへの誘導
>あるっぽい
>
>・code-push
>https://docs.expo.io/versions/v31.0.0/guides/configuring-ota-updates
>
>・sentry
>https://docs.expo.io/versions/v31.0.0/guides/using-sentry
>
>・image picker
>https://docs.expo.io/versions/v31.0.0/sdk/imagepicker
>
>・mail
>https://docs.expo.io/versions/v31.0.0/sdk/mail-composer
>
>・fileSystem
> react-native-fsがある
>
>・realm => ない
>・sqlite => ある
>
>Push 通知の一斉配信
>・fcmの画面からは無理そう。(androidのみ?)
>
>react-native-firebase
>・analytics困った。が、認証やfirestoreとかはいける

最近はたまにつかっています。


# styleの記述を減らす
開発の時間で結構な時間をStyleSheetを書くのにつかっている気がしており、その時間を減らせないかと思っていました。

試行錯誤中ですが割とよかったこと↓

+ glamorous-nativeつかってみる
    + `color={'white'}`みたいなpropsを渡せるので、stylesheet作るまでもないがinlineで描きたくない時、などに便利。
    + ただ型がちょっと悩ましい　https://qiita.com/tyshgc/items/fbb85363626f045c559a


+ Atom的なコンポネントをガンガン作る(Textとかもreact-nativeからimportせず、自前のcomponent作って色とかを制約入れて使うようにする)

native baseつかえばいいじゃん、みたいな話もあると思うのですが、カスタマイズが逆につかれたりするので入れていません。

# アプリがバックグラウンドから戻った時に、読み込み直ししたい。
アプリを終了せずにバックグラウンドから復帰した時に、時間がたっていたら読み込み直しをしたい。
みたいなことがよくあると思うので、独自のコンポネント作って対応しています。

こちらを参考にさせていただきました
https://gist.github.com/janicduplessis/599f57df101981230b8e73129937f659

# 残り
思い出したら追記します。


# まとめ
１年間、変化はありましたが、そこまで大きな不満なく開発できているので、来年も ReactNativeでの開発を続けていこうと思いました。