2016-08-31 10 views
2

これはまったく別の状況で、直接的な解決なしに浮かび上がって見た質問です。私はまた、私が望むコードを実行するためにNavigationをどのように持っているかについていくつかのサンプルを示していたことを何人かの人々から聞いたことがあります。それらのほとんどはサードパーティのソリューションでロールしています。 <View>。いくつかのコンテキストを持っている問題についてはリアクションネイティブのナビゲータボタンからコンポーネント関数を呼び出す

が、これは我々が達成しようとしているものである:

class Example extends Component { 
    componentRouteMapper() { 
     switch(route.id) { 
      case 'home' return <Home navigator={navigator} { ...this.props } /> 
     } 
    } 

    navigationBarRouteMapper = { 
     LeftButton: (route, navigator, index, navState) => { 
      return <TouchableOpacity onPress={this.onLeftPressed.bind(this)}> 
       <Text>Left Button</Text> 
      </TouchableOpacity> 
     }, 
     RightButton: (route, navigator, index, navState) => { 
      // ... Same as left 
     }, 
     Title: (route, navigator, index, navState) => { 
      return <Text>{route.id}</Text> 
     } 
    } 

    render() { 
     return <Navigator initialRoute={{id: 'home'}} 
      renderScene={this.componentRouteMapper} 
      navigationBar={ 
       <Navigator.NavigationBar { ...this.props } 
        routeMapper={this.navigationBarRouteMapper}/> 
      } 

    } 
} 

は、当然のことながら、あなたはのコンテキスト内からナビゲーションバーのロジックを処理できるようにしたいとしていますレンダリングされたコンポーネントこの場合、<Home />となります。そのコンポーネントのアクティブインスタンスから状態/小道具を共有できるようにしたいと考えています。

export default class Home extends Component { 

    onLeftPressed() { 
     console.log('Pressed left button') 
    } 

    render() { 
     return <View> 
      <Text>Home Component</Text> 
     </View> 
    } 
} 

ので、手元に問題がある...どのようにnavigationBarRouteMapper

答えて

1
から onRightPressed()を呼んでください:上記のコードを実行すると、あなたがそうのように、 onLeftPressed()は、ご自宅のコンポーネントで宣言されていても、エラーが発生します

実際には非常に簡単ですが、ルータにコンポーネントを注入するなどの他のアプローチがありますが、Reduxメソッドをconnect()メソッドでRouteオブジェクトに渡すことは面倒です。

私は、あなたの状態を管理するために使用しているものに関係なく、簡単で効果的なソリューションを考え出しました。 注射。そうです、ちょうどあなたのnavigationオブジェクトに直接呼び出す必要があるものを注入してください。

navigationオブジェクトは、this.props.navigatorからコンポーネント内からアクセスでき、私たちにとっては幸運なことに、Javascriptオブジェクトは変更可能であり、性質上参照によって渡されます。

navigationBarRouteMapper = { 
    LeftButton: (route, navigator, index, navState) => { 
     return <TouchableOpacity onPress={navigator.__onLeftNavButtonPressed}> 
      <Text>Left Button</Text> 
     </TouchableOpacity> 
    }, 
    RightButton: (route, navigator, index, navState) => { 
     // ... Same as left 
    }, 
    Title: (route, navigator, index, navState) => { 
     return <Text>{navigator.navTitle || route.id}</Text> 
    } 
} 

あなたはその私に気付くでしょう:これは最初のコードを少し変更することができます、我々はナビゲーターオブジェクトに加えた変更は、そうnavigationBarRouteMapper

に注入されるナビゲータに反映されることを意味しますonPressの値を{this.onLeftPressed.bind(this)}から{navigator.__onLeftNavButtonPressed}に変更しました。使用されている名前は明らかに変更できますが、二重のアンダースコアの接頭辞が好きです。

あなたは、私が{navigator.navTitle || route.id}だけではなくroute.idを返すようにタイトルを変更し、これが意味することは、それが利用できる場合には、ナビゲータからnavTitleプロパティを使用し、そうでないならば、それはのIDを使用することであることもわかりますスタックの最上部のルート。

これで、<Home />コンポーネントに変更を加え、navigationBarRouteMapperが必要なコードを実行できるようにしました。

class Home extends Component { 

    constructor(props) { 
     super(props) 
     var navigator = this.props.navigator 
     navigator.navTitle = 'Home' 
     navigator.__onLeftNavButtonPressed = this.onLeftPressed.bind(this) 
    } 

    onLeftPressed() { 
     console.log('Pressed left button') 
    } 

    render() { 
     return <View> 
      <Text>Home Component</Text> 
     </View> 
    } 
} 

あなたが変更された唯一のものを見ることができるように、我々はnavigatorオブジェクトに機能し、タイトルを注入しconstructor(...)を追加しました。ここで左ボタンをクリックすると、Homeコンポーネント内でonLeftPressed関数が実行されます。

カスタムコンポーネントのサブクラスを作成することで、これをもう少し抽象化することができます。たとえば:

import React, { Component } from 'react' 

export default class NavComponent extends Component { 
    constructor(props) { 
     super(props) 
     console.warn('Constructed') 
     var navigator = this.props.navigator 
     navigator.navbarTitle = this.__onNavTitleRequested(); 
     navigator.__onLeftNavButtonPressed = this.__onLeftNavButtonPressed.bind(this) 
     navigator.__onRightNavButtonPressed = this.__onRightNavButtonPressed.bind(this) 
    } 


    __onLeftNavButtonPressed() { 

    } 

    __onRightNavButtonPressed() { 

    } 

} 

これは、左右のナビゲーションボタンの機能は、常に彼らは未定義の関数を呼び出すしようとするため、アプリケーション・エラーを防ぐことができます何もしない場合でも、設定されていることを保証します。また、__onNavTitleRequestedへの参照があることに気づくでしょうが、これにはデフォルト機能はありません。サブクラスに__onNavTitleRequestedを定義する必要があります。そうしないと、アプリケーションが正しく実行されません。タイトルを設定しないと、常に最後に設定されたタイトルが使用されるため、タイトルバーに不適切なタイトルを持つコンポーネントを持つことは安全です。

次のようになり、これを実装する例は:

import React from 'react' 
import NavComponent from './path/to/nav-component.js' 

export default class Home extends NavComponent { 
    __onNavTitleRequested() { 
     return 'Home' 
    } 

    __onLeftNavButtonPressed() { 
     console.log('Left navigation button pressed') 
    } 

    __onRightNavButtonPressed() { 
     console.log('Right navigation button pressed') 
    } 

    render() { 
     return <View> 
      <Text> Home Component </Text> 
     </View> 
    } 
} 

これは、左/右ボタンにイベントを登録し、ホームコンポーネントのタイトルを設定します。ナビゲーションバー全体を隠すためにtrueまたはfalseを返す__hasNavigationBar関数、または右ボタンに表示されるコンポーネントを返す関数__rightNavButtonが必要な場合など、さらに多くの情報をNavigatorオブジェクトに注入することができますTouchableOpacityボタンの

これまでにも述べたように、これを行う方法はほかにもありますが、私のアプリケーションでこの方法でReduxを使用していると考えると、最も簡単な方法でしたが、問題はありませんでした。

-2

これを行う別の方法は、react-native-event-listenerのようなイベントバスを使用することです。私はこの方法で問題を解決することができました。それはHobbyist's solutionよりずっと簡単です。

基本的には、ボタンが受信者にメッセージを送信し、受信者(コンポーネントのコンテキスト内にある)が必要な処理を実行するという仕組みです。

関連する問題