2018.04.17

react-navigation を使いこなそう


こんにちは。次世代システム研究室のT.M. です。

はじめに


React Native では、ページ遷移のためにreact-navigation を利用することをReact Native の公式ドキュメントで推奨しています。
ただ、私の所感に過ぎませんが、react-navigation について技術ブログ等で応用的な利用の仕方を書いているものは少ないように感じます。また、アーキテクチャとしてredux を選択するのならば、react-native-router-flux を使うべきですが、redux を選択しないのならば、react-navigation で良いかと考えます。そこで、react-navigation で様々なページ遷移のする方法について解説致します。

カード遷移


横からカードが出てくるように遷移する、もっとも一般的な遷移です。以下は、ScreenA からScreenB へカードで遷移して、Back ボタンでScreenA に戻ります。


このような遷移をするためには以下のようにNavigator を記述すれば良いです。

const AppNavigator = StackNavigator(
  {
    ScreenA: {
      screen: ScreenA
    },
    ScreenB: {
      screen: ScreenB
    }
  },
  {
    headerMode: "none"
  }
);

モーダル遷移


下から出てくるように出現する遷移です。異なるページの出現に使われることが多いです。以下は、ScreenA からScreenC へモーダルで遷移して、Back ボタンでScreenA に戻ります。


このような遷移をするためには以下のようにmode オプションを追加したNavigator を記述すれば良いです。

const AppNavigator = StackNavigator(
  {
    ScreenA: {
      screen: ScreenA
    },
    ScreenC: {
      screen: ScreenC
    }
  },
  {
    headerMode: "none",
    mode: "modal"
  }
);

モーダルorカード遷移


一つのページから遷移先によってカードかモーダルが分かれる遷移です。以下は、ScreenA からScreenB へはカードで遷移して、ScreenA からScreenC へはモーダルで遷移しています。


このような遷移をするためには以下のように、モーダルで遷移するNavitator とカードで遷移するNavigator を組み合わせたNavigator を記述すれば良いです。

const AppNavigator = StackNavigator(
  {
    Stack1: {
      screen: StackNavigator(
        {
          ScreenA: {
            screen: ScreenA
          },
          ScreenB: {
            screen: ScreenB
          }
        },
        {
          headerMode: "none"
        }
      )
    },
    ScreenC: {
      screen: ScreenC
    }
  },
  {
    headerMode: "none",
    mode: "modal"
  }
);

モーダル->カード遷移


モーダルで遷移した先で、カードでの遷移する遷移です。以下は、ScreenA からScreenC へはモーダルで遷移して、ScreenC からScreenD へカードで遷移します。ScreenC およびScreenD では、close ボタンでScreenA に戻ります。


このような遷移をするためには以下のようなモーダルorカード遷移のNavigator と組み合わせる順番を逆にしたNavigator を記述すれば良いです。

const AppNavigator = StackNavigator(
  {
    ScreenA: {
      screen: ScreenA
    },
    Stack2: {
      screen: StackNavigator(
        {
          ScreenC: {
            screen: ScreenC
          },
          ScreenD: {
            screen: ScreenD
          }
        },
        {
          headerMode: "none"
        }
      )
    }
  },
  {
    headerMode: "none",
    mode: "modal"
  }
);

循環積み重ね遷移


循環した遷移であり、ページがすべてスタックする遷移です。以下は、ScreenA からScreenBへ、ScreenB からScreenA への循環した遷移を繰り返し、重なった分だけback ボタンで1ページずつ戻ります。


このような遷移をするためには以下のような特別なオプションなど不要であり、普通のNavigator を記述すればよいです。

const AppNavigator = StackNavigator(
  {
    ScreenA: {
      screen: ScreenA
    },
    ScreenC: {
      screen: ScreenC
    }
  },
  {
    headerMode: "none"
  }
);

循環再利用遷移


循環した遷移であり、同じページの場合、再利用する遷移です。以下は、ScreenA からScreenB へ、ScreenB からScreenA への循環した遷移を繰り返すが、back ボタンで1ページしか戻れません。


このような遷移をするためには以下のようにinitialRouteKey オプションを追加したNavigator 記述し、ページ遷移で呼び出す際にkey をつければ良いです。

const AppNavigator = StackNavigator(
  {
    ScreenA: {
      screen: ScreenA
    },
    ScreenC: {
      screen: ScreenC
    }
  },
  {
    headerMode: "none",
    mode: "modal",
    initialRouteKey: "screena"
  }
);

<Button
  title="toA"
  onPress={() => this.props.navigation.navigate({ routeName: "ScreenA", key: "screena" }) }
/>

<Button
  title="toB"
  onPress={() => this.props.navigation.navigate({ routeName: "ScreenB", key: "screenb" }) }
/>

navigate の引数として、key を付けた場合、同一key への遷移ではページがスタックされずに戻る処理が走ります。
Navigator のinitialRouteKey のオプションを付けなかった場合、最初に表示されるScreenA にはscreena ではない、別のkey が自動で設定されるため、ScreenA -> ScreenB -> ScreenA という一つScreenA が多くスタックされてしまいます。ただし、initialRouteKey のオプションはドキュメントには記述されておらず、ソースコードから発見したもののため、使えなくなることがあるかもしれないので、ご注意下さい。

さいごに


react-navigation のちょっとした応用の遷移について説明をしました。
ドキュメントが一部足りなく、また、技術ブログ等での解説が少ないため、react-navigation を使いずらいように感じていたかもしれませんが、シンプルに記述でき、React Native の公式が推奨しているので、react-navigation を使っていくべきだと思います。

次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。インフラ設計、構築経験者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。

皆さんのご応募をお待ちしています。