Category: アプリ

  • React Nativeの認証フローを考える

    React Nativeの認証フローを考える

    React Nativeのアプリ開発やReactのSPA開発において認証フローは、クオリティを左右する重要な要素であることは間違いない。 実際、検索結果には、認証フローに言及した記事や質問が投稿されていて関心の高さが伺える。その内容としては、ルーター設計における認証フローに関するものが多くを占めている印象だ。 そしてReact Nativeのルーター設計には、React Navigationやreact-native-router-fluxが使われるが、いずれもルーター・ナビゲーションライブラリであって認証ロジックを提供していない。すなわちルーターで良しなに対応するか、自作の認証ロジックをこしらえる必要がある。 このエントリーでは、React Nativeの認証フロー について考えてみたい。 そもそも… そもそもReact Navigationの公式ドキュメントに、認証フローに言及したページがある。これはナビゲーションロジックを駆使して認証コンポーネントとプライベートコンポーネントを振り分けるというものだ。 まったくもって理にかなう認証フローだと思う。 その内容で十分だと思うならば、そちらを参考にするのがよいだろう。ただし認証ロジックを提供するものではないことは理解しなければならない。 認証フローのデモンストレーション AppScreen.js AppNavigator定数がメインナビゲーションに該当する。認証後に表示されるコンポーネントだ。AppNavigatorをcreateAppContainer(…)にセットした上で、withAuthenticator(…)にセットする。withAuthenticatorは、高階コンポーネントになっていて条件によって別コンポーネントを返す。 withAuthenticator.js まずconstructor(props) {…}で認証トークンを取得済みか否かを確認する。その結果で認証コンポーネントかプライベートコンポーネントに振り分ける。 認証トークン取得済みであればprops.authenticate(true);を実行して、this.props.isAuthenticatedの状態を更新する。これによってif (isAuthenticated) return <Component />;のコンポーネントが返される。すなわちこれは、AppScreen.jsで定義したcreateAppContainer(AppNavigator)を参照する。 認証トークン未取得であればprops.signIn();を実行して、this.props.authStageの状態を更新する。これによってswitch (authStage) {…}のcase types.SIGN_IN:が該当する。したがってサインインコンポーネントが返される。 authentication.js Reduxのaction-creatorとaction-type、reducerをまとめている。いわゆるDucksというデザインパターンだ。 stateにはisAuthenticatedとauthStageを定義している。この状態を更新するためにaction-creatorのforgotPassword、signUp、signIn、authenticateがある。 forgotPassword、signUp、signInは、authStageの状態を担当し、action-typeの定数値に更新する。 authenticateは、isAuthenticatedの状態を担当し、真偽値を受け取って更新する。 まとめ React Nativeの認証フロー に関する内容だった。 この内容ではReact Navigationを使っているが、react-native-router-fluxであっても再現可能だ。AppScreen.jsのwithAuthenticator(…)にreact-native-router-fluxのルーターコンポーネントをセットすればよい。 ただこの認証フローにも悩みどころがある。 React Navigationかreact-native-router-fluxに関わらず、認証コンポーネントはナビゲーション管轄外になっていることで、ヘッダーが表示されない。認証画面などにもヘッダーが必要ならば、NativeBaseなどのUIコンポーネントでヘッダーUIを挿入したり、各コンポーネントもナビゲーション化しなければならない。 UIコンポーネントを使う手段は、ヘッダーUIに差異が発生するから却下だろう。ナビゲーション化は、せっかく振り分けたのに、どこかモヤモヤする。 素直にReact Navigationの認証フローに倣ったほうがよいのかもしれない。 このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。

  • React NavigationのcreateBottomTabNavigatorでヘッダーUIを表示する方法

    React NavigationのcreateBottomTabNavigatorでヘッダーUIを表示する方法

    React Navigationのルーティング設定で、ヘッダーUIとタブバーUIを含むとき、タブ切り替えナビゲーションを担うcreateBottomTabNavigatorを使う。 ところが、createBottomTabNavigatorではヘッダーUIが表示されない。 タブバーUIにおいて、ヘッダーUIが不要なケースがあるかもしれないからヘッダーコンポーネントを含めていないと思われる。しかしその一方でcreateStackNavigatorだとヘッダーUIが表示される。 感の鋭いひとは、気づいたかもしれない。createBottomTabNavigatorとcreateStackNavigatorを複合的に使うことでヘッダーUIとタブバーUIの配置を実現できるということに。 このエントリーでは、ヘッダーとタブバーの要件を満たすReact Navigationのカスタマイズ方法を紹介したい。 createBottomTabNavigatorでタブバーUIを表示する 以下ソースコードを見てほしい。 createBottomTabNavigator APIを使っている。createBottomTabNavigatorの引数には、オブジェクト形式でHome, Cart, Settingプロパティが確認できる。各プロパティには、さらにオブジェクト形式でscreen, navigationOptionsプロパティがあり、screenに任意のReact.Componentを適用して、navigationOptionsでタブラベルを設定している。 タブバーUI設置は実現しているが、例によってヘッダーUIは表示されない。 createStackNavigatorでヘッダーUIを表示する 以下ソースコードを見てほしい。 行数が増えているが、実は、いたってシンプルだ。前述のソースコードからの変更点は、screenプロパティにcreateStackNavigatorを書いている。以下、差分キャプチャを見てほしい。 createBottomTabNavigatorのscreenにcreateStackNavigatorを展開しているだけだ。オブジェクトがネストして分かりにくさを覚えるが、createBottomTabNavigatorとcreateStackNavigatorのコンポーネントを通して任意のコンポーネントが表示される仕組みになっている。 果たして、タブバーUIとヘッダーUIを表示することができた。 まとめ ヘッダーUIとタブバーUIの要件を満たすReact Navigationのカスタマイズ方法の紹介だった。 「createBottomTabNavigatorのscreenにcreateStackNavigatorを展開している」と表現して、わたし自身があらためてスッキリした。ネストが多くてややこしいのだけれど、createBottomTabNavigatorのつもりで記述を済ませてからcreateStackNavigatorを書き加えると迷子になりにくいかもしれない。 このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。

  • [React Native] keyboardType propsのキーボードビジュアルの違い

    [React Native] keyboardType propsのキーボードビジュアルの違い

    アプリケーションのテキストフィールドのキーボードが、入力タイプによって最適化されることを思い出せるだろうか。メールアドレスフィールドだったり、電話番号フィールドだったりがわかりやすいかもしれない。メールアドレスを入力する場合は、@やドットが配置されていて、電話番号を入力する場合は、数字や#*+等の記号が配置されている。 このようにユーザーが入力しやすい機構が用意されているわけだが、テキストフィールドの入力タイプはエンジニアが明示しておく必要がある。 HTMLならば、<input>のtype属性にtextやpassword、numberなどを指定して、React Nativeならば、<TextInput>のkeyboardType propsにdefaultやnumber-padなどを指定するとキーボードが最適化される。 このエントリーでは、keyboardType propsの指定におけるキーボードビジュアルの違いを確認したい。 キーボードタイプの対応表 default number-pad decimal-pad numeric email-address phone-pad ascii-capable numbers-and-punctuation url name-phone-pad twitter web-search visible-password default number-pad decimal-pad numeric email-address phone-pad ascii-capable numbers-and-punctuation url name-phone-pad twitter web-search visible-password まとめ keyboardType propsの指定におけるキーボードビジュアルの違いについて確認してきた。プラットフォーム間においても、未対応のものがあって案件によって使い分けを検討するケースもあるかもしれない。とはいえ、適切なキーボードタイプの設定は、ユーザビリティ向上が見込めるため積極的に適用すると良さそうだ。

  • [react-native-router-flux] フォーカスされてるタブのアイコンにアクティブカラーをつける方法

    [react-native-router-flux] フォーカスされてるタブのアイコンにアクティブカラーをつける方法

    react-native-router-fluxを使ってRouter設計するとき、タブバーUI用にTabsコンポーネントがある。アプリのスクリーン下部にあるナビゲーションUIのことだ。 タブバーデザインにおいてよほどの理由がない限りは、Tabsコンポーネントを使う。UIコンポーネントを利用すれば同様のものが設置できるし、自作タブバーにすることもできるが、わざわざそうする理由もない。なにより遷移設定が面倒くさい。 そんなTabsコンポーネントであるが、アクティブ時のカラーや非アクティブ時のカラーをカスタマイズするpropsがある。これを書き加えることで、タップしたときに色を変えられるわけだ。 しかしアイコン表示において手こずった事案があった。 このエントリーでは、フォーカスされているタブのアイコンにアクティブカラーをつける方法を共有したい。 react-native ^0.59.8 react-native-router-flux ^4.0.6 native-base ^2.13.4 タブバーにアイコンを表示する まずはRouter設定をする。使うコンポーネントは、 <Router> <Tabs> <Scene> の3つ。タブは「ホーム、カート、設定」を切り替える単純なものを想定している。 上記ソースコードのコメントアウト行を見てほしい。 各タブにアイコン設置するため、<Icon>を使っている。これはNativeBaseのIconコンポーネントだ。<Scene>にそれぞれ設定することでアイコンが表示される。以下のようになると思う。 つづいては、タブがフォーカスされたときにアクティブカラーを着色する工程だ。 タブがフォーカスされているとき(されていないとき)のカラーを指定する タブをタップしてフォーカスされたときに、テキストおよびアイコンがアクティブであるとわかるようにカラーを変えたい。 上記ソースコードのコメントアウト行を見てほしい。 activeTintColor propsがアクティブ時のカラーコードで、inactiveTintColor propsが非アクティブ時のカラーコードを設定している。いずれのpropsも文字列を受け付ける。 現在フォーカスされているホームタブのテキストはアクティブカラーになっている。ところが、アイコンのカラーは変わっていない。それもそのはずで、外部のコンポーネントなのだから仕方がない。 <Icon>は、NativeBaseのコンポーネントだった。アイコンのカラーを変更するには、style propsにオブジェクト形式で、CSSを記述すればよい。 上記ソースコードのコメントアウト行を見てほしい。 <Scene>のicon propsに設定した関数の引数から、focusedを受け取っている。これは真偽値が格納されている。つまりタブがフォーカスならtrueというわけだ。 style propsに、focusedがtrueならアクティブカラーで、falseなら非アクティブカラーがを渡している。これにてアイコンにもアクティブカラーを付与することができた。 まとめ フォーカスされているタブのアイコンにアクティブカラーをつける方法の共有だった。 この内容では、NativeBaseのIconコンポーネントを使っているが、自作のsvgアイコンやほかのUIコンポーネントであっても同様のことができるはずだ。focusedを受け取ってフォーカスか否かを確認して切り替えればよいのだから。 このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。

  • [React Native] ExpoのPush Notificationsでプッシュ通知する

    [React Native] ExpoのPush Notificationsでプッシュ通知する

    このエントリーでは、ExpoのPush Notifications APIの実装、そしてプッシュ通知のテスト送信まで一連を紹介したい。 難しいのでは?と思ったあなたも大丈夫。 私は最近までプッシュ通知とは無縁のマークアップエンジニアで、スマホアプリ開発の経験といってもハイブリッドアプリ開発に携わった程度のものだ。プッシュ通知にどのような手続きが必要なのか全く無知な状態だったわけだが、テスト送信までした所感として、「簡単」だと言い切れる。 というのも結局は手続きというものはなく、証明書作成が不要だ。またAPNs/GCMといったプッシュ通知サービスへのリクエストもExpoが良しなにこなしてくれるため、条件分岐も不要だ。 ともあれ体感してもらうのが早かろうと思う。 コーディング App.js 重要なAPIは、NotificationsとPermissions、Constantsの3つ。デバイストークンを取得するまでの処理が記述されている。トークン取得に関わる処理はregisterForPushNotificationsAsync()メソッドに書かれていて、Appコンポーネントがマウントされた時点で、実行される。 デバイストークンを取得 プッシュ通知は「”◯◯”は通知を送信します。よろしいですか?」のアラートを許可することでデバイストークンが得られる。アラートに「ExponentPushToken[**********]」が表示されていれば、ひとまず成功だ。デバイストークンはテスト送信ツールに入力するため、メモしておこう。 プッシュ通知をテスト送信 「Push notifications tool」に通知したい内容を入力する。EXPO PUSH TOKEN (FROM YOUR APP)のデバイストークンが必須項目で、あとは適宜必要なものは入力するとよい。今回のプッシュ通知は、MESSAGE TITLEとMESSAGE BODYのみ入力している。Send a notificationボタンをクリックすれば、プッシュ通知サービスに送られる。 EXPO PUSH TOKEN (FROM YOUR APP) MESSAGE TITLE MESSAGE BODY Play sound JSON DATA TTL (SECONDS) IMAGE AUDIO (IOS ONLY) VIDEO (IOS ONLY) iOS MESSAGE SUBTITLE MESSAGE CATEGORY BADGE COUNT…

  • Expo Clientアプリにプロジェクトが表示されないときの解決方法

    Expo Clientアプリにプロジェクトが表示されないときの解決方法

    create-react-native-appでプロジェクト作成して、Expo (Run on iOS simulator) で確認する。デバッグには欠かせない一連の作業だ。 ところが想定していたプロジェクト画面ではなく「There was a problem loading the requested app.」のメッセージが表示される。 なんのことか分からず$ create-react-native-app my-new-projectによるプロジェクト作成ではなく、$ expo init my-new-projectを試すが、結局「There was a problem loading the requested app.」メッセージが表示される。 このように見に覚えもなくExpo Clientに表示できなくなってしまった場合には、手動による作業が必要になるようなのだが、ドキュメントにも書いてないことは分からなくても仕方がない。 このエントリーでは、「There was a problem loading the requested app.」に関わる問題の解決方法を紹介したい。 問題の画面 「There was a problem loading the requested app.」のメッセージが確認できる。読み込み中に問題が発生したってことらしい。 つづいて下段落に目を移すと「The experience you requested requires a newer version of…

  • NativeBaseの’Roboto_medium’フォントをプリロードする方法

    NativeBaseの’Roboto_medium’フォントをプリロードする方法

    NativeBaseのText APIは、テキストを表示する場合に使うのだが、Androidの表示においては、事前にRoboto_mediumフォントを読み込ませなければならない。 さもないと、次のエラー内容が発生する。 fontFamily “Roboto_medium” is not a system font and has not been loaded through Font.loadAsync. Roboto_mediumがシステムフォントじゃないから、Font.loadAsync()で読み込むように、とのことだ。 iPhoneのfontFamilyはsystemなのだが、AndroidはRoboto_mediumが指定されている。当該フォントを読み込まなければならないが、fontFamily宣言前にロード完了しておきたいところだ。 このエントリーでは、「fontFamily “Roboto_medium” is not a system font and has not been loaded through Font.loadAsync.」の回避方法を紹介したい。 まずrender直後にif (!this.state.isReady) {…}でisReadyステートを判定する。trueでなければAppLoadingコンポーネントがマウントされる。 フォントは、Font.loadAsync()メソッドで読み込み、その内容をPromise.all([])に追加してreturnする。 AppLoadingコンポーネントのstartAsync propsに与えられたPromiseオブジェクトを解決する。 AppLoadingコンポーネントのonFinish propsが、startAsync propsの解決をトリガーにしてthis.setState({ isReady: true })を実施する。同時にAppLoadingコンポーネントをアンマウントする。 再renderされる。 if (!this.state.isReady) {…}を通過する。 目当てのJSXが表示される。 まとめ ‘Roboto_medium’フォントをプリロードする方法の紹介だった。「fontFamily “Roboto_medium” is not…

  • React NativeのUIコンポーネント「NativeBase」のButton UIが横幅いっぱいにならないようにする方法

    React NativeのUIコンポーネント「NativeBase」のButton UIが横幅いっぱいにならないようにする方法

    React Nativeの開発で、デザインがよほどオリジナルではない限りUIコンポーネント「NativeBase」を使うケースは少なくないと思う。各プラットフォームのスタイル適用を省略できることがメリットだからだ。 なかでもButton APIは重宝されているのではないだろうか。そもそもButton APIはReact Native標準コンポーネントのView APIとTouchableOpacity APIをラップしたもので、タップすると半透明になり、Material Design風にスタイルされている。 これを独自コンポーネントで定義するのは、なかなか面倒で骨が折れる。よほどオリジナルなデザインでない限りは、使い勝手のよいコンポーネントAPIだ。 さてNativeBaseのButton APIを考えなしにView APIなどのレイアウトコンポーネント内に配置すると横幅いっぱいに表示される問題に遭遇する。fullプロパティを付与していないにも関わらずだ。 このエントリーでは、Buttonが横幅いっぱいにならないようにする方法を紹介したい。 まずJSX内に見えるContainerとContentタグもNativeBaseのコンポーネントAPIだ。いずれもReact Native標準コンポーネントのView APIが基になっている。 重要なところは、Contentタグのstyle={{alignItems:’flex-start’}}だ。CSSのalign-itemsプロパティにより左寄せにしている。そもそもalign-itemsは、縦方向に関わるものなのだが、View APIの主軸は縦方向だ。つまりflex-direction:columnのような状態になっている。 主軸が縦方向(column)の場合は、align-itemsは横方向に関わる指定に変わるため、flex-startで左寄せになったというわけだ。 これはContainerやContent以外のレイアウトコンポーネントであっても同様である。たとえばViewタグに内包されるような場合は、Viewタグにstyle属性を付与すればよい。 このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。

  • react-native-router-fluxのタブバーに通知バッジを表示させる方法

    react-native-router-fluxのタブバーに通知バッジを表示させる方法

    react-native-router-fluxには、タブUIを構成するTabs APIが用意されている。スマホアプリ特有のスクリーン下部に配置されたユーザーインターフェースで、各タブメニューは、それぞれのスクリーンを表し、Routerとして機能するわけだ。 ところで、いずれかのスクリーンで新着メッセージなどがあることを知らせるために通知バッジを使うことは一般的だろうと思う。そしてこのような場合、通知バッジの配置場所として、タブUIに寄り添う形にすることも有り得ることだと思う。 しかしタブUIを構成するTabs,Scene APIに通知バッジを表示させるであろうプロパティが見当たらない。 断念せざるを得ないのだろうか?別の箇所に配置せざるを得ないのだろうか? 否だ。通知バッジを反映させる専用のプロパティは無いが、少しカスタマイズすればタブバーにも通知バッジを配置することができる。カスタマイズといってもネイティブのソースコードではなく、あくまでJavaScript内の話だ。 このエントリーでは、React Nativeのナビゲーションライブラリ「react-native-router-flux」の、タブバーUIに通知バッジを表示させる方法を紹介したい。 通知バッジを配置する Scene APIのiconプロパティ(props)を見てほしい。ホームスクリーンのSceneタグのiconには、矩形用のViewタグでIconタグとTabbarBadgeタグ、TabbarBadgeTextタグが確認できると思う。TabbarBadgeとTabbarBadgeTextはstyled-componentsライブラリでスタイルするためのタグで、名称は任意だ。const TabbarBadge = styled.Viewとconst TabbarBadgeText = styled.Textが代入している行になる。 果たして、タブに通知バッジが表示されるはずだ。

  • 【Electron+Next.js】デスクトップアプリジェネレーターNextronで簡単にElectronアプリ開発をしよう

    【Electron+Next.js】デスクトップアプリジェネレーターNextronで簡単にElectronアプリ開発をしよう

    Electronデスクトップアプリのレンダラープロセス設計において、求められるスキルセットはWebアプリ案件とそれほど違うところはない。 静的コンテンツで済むのであれば、HTML&CSSとわずかなJavaScript(jQuery)があればよい。コンテンツ更新が頻発するのなら、SPAを考慮したい。ReactやVue.js、Angularなどが候補になるだろう。 SSRフレームワークで知られるNext.jsやNuxt.jsを得意とするなら、十分に活用できるはずだ。ただしレンダラープロセスのウインドウ生成には、起点となるHTMLファイルを定義する都合があるため静的HTMLにエクスポートする必要がある。 そもそもdevelopment時点ではHTMLファイルがない。pagesフォルダ配下のjsファイルがルーティングと関連付くかたちでページ生成されるためである。ごく単純なSPA構築ライブラリと相違するポイントであって、Electronとともに使うときには、非常に難解な要素といえる。 それでもElectron+Next.jsが候補されているなら、もっとも効率のよい始め方がある。Next.jsを基に開発が進められる「Nextron」を使ってみてはどうだろう。 Nextronとは Nextronは、デスクトップアプリジェネレーターである。利用者は、Electron+Next.js環境が整った状態で開発を開始することができて、CLIでプロジェクト初期化や開発、ビルドの設定がされているため手間が省ける。 さらにNextronには、さまざまなケースを想定したexampleが用意されていて、要件を満たしてくれる。プロジェクト要件に近いexampleから初期化できるわけだ。大変有り難い仕様になっている。 特徴 使い方 Nextronをインストール Nextronを-gオプションでインストールする。これによりnextronコマンドを使用できるようになる。 nextronインストールの無事を確認してみよう。 プロジェクトを初期化 Nextron環境を初期化しよう。下記プロジェクト名は任意で構わない。 Nextronを–globalにインストールしない場合の初期化方法も用意されている。 依存関係をインストール Nextron環境に依存関係するパッケージモジュールをインストールしよう。 果たして、node_modulesフォルダが生成されていることだろう。 開発モードを実行 不測のことがなければ、ウインドウが立ち上がる。開発モードでは簡易Webサーバーが起動している。「http://localhost:8888/home」にアクセスすれば、ブラウザでも確認できるはずだ。 ビルドを実行 「dist」フォルダが生成される。フォルダ配下にインストーラーや実行ファイルがあることを確認しよう。 まとめ Electron+Next.js 要件が求められるプロジェクトならば、Nextronはよい選択ではないだろうか。環境構築が初めてならなおさらだ。自身で依存関係パッケージモジュールをかき集めるには、とても骨が折れる。 それならNextron環境で、プロジェクトにマッチするexampleを活用するのが賢明と思える。exampleの記述には、Electronたらしめるipc通信に関することがhelpersにまとめられている。Web制作者にとって馴染みないipc通信をサポートするメソッドが使えるのは大変有り難い次第だ。 これほどの作り込まれたNextronは、デスクトップアプリジェネレーターといって申し分ない。ぜひ検討してみてほしい。