Cover image for react-native-router-fluxのonRightをカスタマイズする(part2)
react-nativereact-native-router-flux

react-native-router-fluxのonRightをカスタマイズする(part2)

August 26, 2019

5 min read

mitsuruogMitsuru Ogawa

react-native-router-fluxの小ネタです。

前回の話はこちら。

前回はアプリの NavBar の右側にあるボタン(以下、RightButton)をクリックした時に、次の画面に props を渡したいようなユースケースを想定していましたが、今回は RightButton を props の条件で出し分けしたいと思います。

次のような手順で実現できそうです。

  1. PageComponent 内部で RightButton を出す
  2. RightButton をタップした時に、Component 内部のタップハンドラ(private function)を実行する
  3. 外部からの props の値で RightButton を出し分けする

コードは全て TypeScript です。

PageComponent 内部で RightButton を出す

RightButton の追加方法はいくつかあるのですが、今回は PageComponent に static なnavigationOptionsプロパティを追加して、この中で RightButton 用の Component を定義します。

この方法というものがいくつかあって、それぞれ期待する動きをしないので辛いです。

// ...
import { NavigationScreenProps } from "react-navigation";

class Page extends React.Component<State, Props> {
  static navigationOptions = ({ navigation }: NavigationScreenProps) => {
    return {
      // ここにRightButtonのComponentを渡す
      headerRight: <Button title="+1" />,
    };
  };

  render() {
    // ...
  }
}

navigationOptionsで渡されている関数のnavigationreact-navigationNavigationScreenPropsの型を使います。これは、react-native-router-fluxreact-navigationをベースとして拡張しているためです。

RightButton をタップした時に、Component 内部のハンドラを実行する

RightButton をタップした時に、Component 内部のハンドラを実行するにはButtonComponent のonPressを使えば可能です。しかし、staticプロパティ内部から PageComponent 内の private function を呼び出すにはひと工夫必要でした。

staticプロパティ内部から PageComponent の function を実行するには、props のnavigationを通じて function の参照を渡すことで可能となります。 componentDidMountの中で props のnavigation.setParamを使うことで参照を渡すことができます。

// ...
import { NavigationScreenProp, NavigationScreenProps } from "react-navigation";

export interface Props {
  navigation: NavigationScreenProp<any, any>;
}

class Page extends React.Component<State, Props> {
  static navigationOptions = ({ navigation }: NavigationScreenProps) => {
    return {
      headerRight: <Button title="+1" />,
    };
  };

  componentDidMount() {
    // ここでハンドラの参照をセットする
    this.props.navigation.setParams({ onRight: this.onRight });
  }

  // ...
}

渡されたハンドラの参照を次のようにnavigationOptionsで使うことができます。

// ...

class Page extends React.Component<State, Props> {
  static navigationOptions = ({ navigation }: NavigationScreenProps) => {
    return {
-      headerRight: <Button title="+1" />
+      headerRight: <Button title="+1" onPress={navigation.getParam('onRight')} />
    };
  }

// ...

これで RightButton をタップした時にonRightが呼び出されるようになります。

外部からの props の値で RightButton を出し分けする

外部からの props も上の方法と同様にnavigation.setParamgetParamを使って実現します。

今回は props でhasButtonが渡されるとします。componentDidMountの中で再びnavigation.setParamを使います。

// ...

  componentDidMount() {
    // ここでハンドラの参照をセットする
    this.props.navigation.setParams({ onRight: this.onRight });
+   this.props.navigation.setParams({ hasButton: this.props.hasButton });
  }

// ...

この値をnavigationOptionsの中で使います。

// ...

class Page extends React.Component<State, Props> {
  static navigationOptions = ({ navigation }: NavigationScreenProps) => {
    return {
-     headerRight: <Button title="+1" onPress={navigation.getParam('onRight')} />
+     headerRight: navigation.getParam('hasButton') ?
+       <Button title="+1" onPress={navigation.getParam('onRight')} /> :
+       undefined
    };
  }

// ...

これで props 経由で RightButton を出し分けすることができるようになりました。

。。。大変。

以上