Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Our choice in ReactNative

B72422afc5f3ffc844f672b59122e16d?s=47 joe_re
May 19, 2017

Our choice in ReactNative

B72422afc5f3ffc844f672b59122e16d?s=128

joe_re

May 19, 2017
Tweet

Transcript

  1. Our choice in ReactNative @joe_re

  2. Who am I? • twitter: @joe_re • github: @joe-re •

    working in freee K.K
  3. Released Android app using React Native

  4. Today’s Topics • How was ReactNative? • Using NativeLayer’s assets

    • Architecture of JS Layer • For Release
  5. Notice • 今回作ったアプリはAndroid向けなので、
 基本的には Androidの話です • JS LayerにはなるべくAndroidでしか動かない コードは書かないようにしていますが、
 クロスプラットフォームの話はしません

  6. まずどういうものかDEMO

  7. How was ReactNative?

  8. プロジェクト概要 • 開発期間: 3ヶ⽉月 • 開発メンバー:2名
 - Webフロントメインなエンジニア1名
 - インターン1名

    • モバイルエンジニアは開発メンバーには
 いない
  9. Q: ReactNativeでは
 Webフロントの知⾒見見だけで
 Nativeアプリケーションが
 作れるのか

  10. Q: ReactNativeでは
 Webフロントの知⾒見見だけで
 Nativeアプリケーションが
 作れるのか

  11. やっぱりNativeの知識は必要 • Nativeの資産を⽣生かしたい場⾯面では NativeLayerを書く必要がある • UIコンポーネントもSDKに提供されているも のを使うので、ある程度知識があるとハマり どころは回避しやすい • その他ビルドスクリプトの微調整など

  12. Q: ReactNativeを
 採⽤用して効果的だったか

  13. Q: ReactNativeを
 採⽤用して効果的だったか

  14. 今回の開発体制、
 状況的には正解だったと思う • 開発メンバーにモバイルエンジニアがいない中で、
 使い慣れたReactでフロントが構築できるのは
 ⾮非常に効率的だった • 社内にはモバイルエンジニアがいるので、
 モバイルについていつでも質問はできる環境があった •

    補⾜足として、Javaはチョット書けたし、
 モバイルもまぁ書いたことがないわけではなかった
  15. Using NativeLayer’s assets

  16. 提供している機能をざっくり • NFCタグを読み取り使⽤用履履歴に変換 • 使⽤用履履歴を元に経費申請する • その他Webとの連携 Native Layer JS

    Layer
  17. Android SDKはNFCタグの
 操作を提供している https://developer.android.com/reference/android/nfc/package- summary.html

  18. Android SDKの NfcAdapterを利利⽤用するには • Android SDKの提供するAPIを利利⽤用できるよう にするために、NfcAdapterの機能をラップし たNativeModuleを作成する • Reactのライフサイクルに合わせて、


    作成したNativeModuleのAPIを呼び出す
  19. Wrap NFCAdapter @ReactMethod QVCMJDWPJETUBSU3FBEJOH/GD \ /GD"EBQUFSOGD"EBQUFS /GD"EBQUFSHFU%FGBVMU"EBQUFS SFBDU$POUFYUHFU"QQMJDBUJPO$POUFYU  "DUJWJUZBDUJWJUZSFBDU$POUFYUHFU$VSSFOU"DUJWJUZ

     JG OGD"EBQUFSOVMMccBDUJWJUZOVMM \ SFUVSO ^ OGD"EBQUFSFOBCMF3FBEFS.PEF BDUJWJUZ  OFX$VTUPN3FBEFS$BMMCBDL SFBDU$POUFYU '-"(@3&"%&3@/'$@' OVMM  ^ @ReactMethod public void endReadingNfc() { NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(reactContext.getApplicationContext());; Activity activity = reactContext.getCurrentActivity(); if (nfcAdapter == null || activity == null) { return; } nfcAdapter.disableReaderMode(activity); }
  20. Send to JS Layer class CustomReaderCallback implements ReaderCallback { ReactContext

    reactContext; public CustomReaderCallback(ReactContext reactContext) { this.reactContext = reactContext; } @Override public void onTagDiscovered(Tag tag) { try { analizeTag(tag); } catch (IOException e) { Crashlytics.logException(e); } } private void analizeTag(Tag tag) throws IOException { FelicaReader reader = new FelicaReader(tag); //… 解析処理理 … sendEvent(reactContext, “READ_CARD", payload); } private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) { reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) .emit(eventName, params); } }
  21. ReactNative Side import { NativeModules, DeviceEventEmitter } from ‘react-native'; class

    ReadingCardPage extends React.Component { // … componentDidMount() { NativeModules.NFCReactModule.startReadingNfc(); DeviceEventEmitter.addListener('READ_CARD', this._handleReadCard); } componentWillUnmount() { DeviceEventEmitter.removeListener('READ_CARD', this._handleReadCard); NativeModules.NFCReactModule.endReadingNfc(); } // … }
  22. これだけで簡単に
 Android SDKの機能を
 JSから利利⽤用できる

  23. Architecture of JS Layer

  24. Using Redux • Middleware • redux-thunk • redux-promise-middleware • redux-logger

  25. redux-promise-middlewareを 選択した理理由 • middlewareの層に副作⽤用を押し付けるアプローチはなるべく取ら ない⽅方針(多少個⼈人的な趣向が⼊入ってはいる) • ⾮非同期処理理が⼊入るところで、どうしても時間軸を気にしなくては ならないアクションの発⾏行行だけmiddlewareでどうにかしたかった • ⼤大抵の⾮非同期処理理を伴うアクションは、処理理の開始、成功、失敗

    の3種類類さえあれば⼗十分 = これらはPromiseのstatusにそのまま対 応している • redux-promise-middlewareはPromiseの状態に従って、
 アクションの発⾏行行を⾃自動化してくれる
  26. redux-promise-middleware // action creator const getPost = id => ({

    type: 'GET_POST',\ payload: new Promise(resolve => { setTimeout(() => fetch(`/api/posts/${id}`).then(response => { resolve(response.json()); }), 1000); }) }); // reducer const reducer = (state = {}, action) => { switch (action.type) { case 'GET_POST_PENDING': return { isPending: true }; case 'GET_POST_FULFILLED': return { body: action.payload.body }; default: return state; }; } payloadにpromiseを渡す promiseのstatusの遷移に従い
 actionが⾃自動でdispatchされる
  27. Nativeアプリケーションと ReduxStateとの相性は良い • ReduxStateに画⾯面上の表示の元となっている箇所を全てを押 し込めることで、画⾯面の再構成がいつでも⾏行行えるようになる • モバイルでは、Webよりもエラー復復旧のために
 アプリケーションレイヤーで保持しておかなくてはいけない 情報は多い(Navigationのスタックなど) •

    画⾯面が狭いので、エラー表示⽅方法や復復旧⽅方法も異異なる
 (ネットワークエラー発⽣生時には、画⾯面全体をエラーページ にする→再読み込みボタンで成功すれば画⾯面を戻す、など)
  28. Routerには react-native-router-fluxを選択 • Reduxサポートが厚いので選択 • いい感じに使えて特に不不満はなかった • けど内部で使っていたNavigationExperimentalが RN@0.43からdeplicatedになってしまった •

    今なら公式のreact-navigationがおすすめ
 (個⼈人的に使っている感じでは、違和感もないし、
 Reduxも普通に使える)
  29. HOCの活⽤用 • 以下の処理理はHOCで共通化 • ログイン必須ページのログイン要求 • flex-boxだけでは対応の
 難しい画⾯面のリサイズ
 (リストビューの横幅の再計算とか) •

    Indicatorの表示 • SnackbarなどのNotification表示 • etc…
  30. Example of HOC // for typed hoc pattern: https://github.com/facebook/flow/issues/2521 type

    FunctionComponent<P, S> = (props: P, context: S) => ?React$Element<any>; type ClassComponent<D, P, S> = Class<React$Component<D, P, S>>; type Props = { snackbarMessage: SnackbarMessage, actions: typeof Actions }; export default function ShowSnackbar<D, P, S>( WrappedComponent: ClassComponent<D, P, S>|FunctionComponent<P, S> ): ClassComponent<void, P & Props, {}> { return class _ShowSnackbar extends Component { props: P & Props; state: {}; componentWillReceiveProps(nextProps: Props) { if (this.props.snackbarMessage !== nextProps.snackbarMessage) { this.showSnackbar(nextProps.snackbarMessage); } } showSnackbar(snackbarMessage: SnackbarMessage) { // 表示処理理 } render() { return ( <WrappedComponent {...this.props} /> ); } };
  31. For Release

  32. Crash reporting • 社内で実績があったCrashlyticsを導⼊入 • ReactNativeでも導⼊入は簡単
 (ReactNative向けにreact-native-fabricという npmが提供されている) • モバイルはユーザ環境によって


    予想外のエラーが起きることが多いので、
 できればリリース前に⼊入れておくのが良い
  33. 不不要な権限は削ろう(Android) • 初期状態では以下の権限が要求される
 - USBストレージの読み取り
 - 端末情報とIDの読み取り
 - 他のアプリの上に重ねて表示 •

    USBストレージの読み取りはAsyncStorageを使うために必要だ けど、他の権限は今回のアプリでは不不要 • これらの権限は実はデバッグツールのために要求されているので、 不不要であればリリースバージョンで取り除くようにmanifestを
 書くのが良い
  34. app/src/release/ AndroidManifest.xml • Androidのgradleスクリプトでは
 ディレクトリの規約によりリリース時の Manifestを選択できる <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="jp.co.freee.nfc">

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" tools:node="remove" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" /> </manifest>
  35. Yarnを利利⽤用してLicense表記の 雛形を作る • yarnにはlicensesコマンドがあり、package.jsonの依存定義 からLicense表記を⽣生成するコマンドがある • ReactNativeでは基本的にnpmでpackage管理理をするため、 このコマンドをLisense表記の雛形を作るために使うと便便利利 • ライセンス表記は⼊入れなきゃいけないもの、⼊入れなくても

    良いものの判断は別途しないといけないので、あくまで雛 形として使いましょう
 (会社に法務がいる場合は相談しよう)
  36. AsyncStorageREPL (おまけ)

  37. Access AsyncStorage from Node REPL • 開発中気軽にAsyncStorageの中身を⾒見見たり、
 変更更したりできないのが不不満だった • NodeのREPLからアプリケーションの

    AyncStorageにアクセスしたかった
 (rails consoleみたいなイメージ)
  38. 作った • https://github.com/joe-re/async-storage-repl

  39. DEMO

  40. 興味があれば ぜひ使ってみてください


  41. GraphQLのmeetupやります! https://www.meetup.com/ja-JP/GraphQL-Tokyo/events/239924595/ 5/30(⽕火) 20:00〜22:00

  42. React Native is fun

  43. Thank you for your attention!