2016-08-21 3 views
3

Ich stelle zusammen diese Frage/Antwort-App und kam diese Hürde across:React-native: Bindungs ​​Szene navigationbar

ich eine Funktion in einer Szene aus dem navigationbar auslösen soll. Ähnlich wie bei einer Anmeldung App Ich habe einen Button in der Navigationsleiste eine Antwort einreichen:

RightButton(route, navigator, index, navState) { 
    if (route.name=='TextInputView'){ 
    return <TouchableHighlight 
      underlayColor="transparent" 
      style={{ marginRight:13, marginTop:0}} 
      onPress={() => this.refs.TextInputView.submitSolution()}> 
     <Text style={ styles.leftNavButtonText }>Done</Text> 
     </TouchableHighlight> 
    } 

die renderscene (Route, Navigator) sieht so aus:

if (route.name == 'TextInputView'){ 
    return <TextInputView ref="TextInputView" navigator={navigator} {...route.passProps}/> 
} 

und natürlich in der "TextInputView" Komponente Ich habe eine "submitSolution" -Funktion ...

Problem ist, wenn ich in der Szene bin und drücke die "Fertig" - bekomme ich immer: "undefined ist kein Objekt (Bewertung '_this2.refs.TextInputView ')

wie immer: Danke für Ihre Hilfe

Antwort

9

Nun, Sie können es tun, indem Sie alles in Bezug auf die Vorlage in der Szene selbst zu halten.

Wie?

Sie tun es, indem Sie eine Schaltfläche in der Navigationsleiste bei Bedarf injizieren.

Hier ist eine Lösung, die ich für ein Projekt erstellt arbeite ich an: https://rnplay.org/apps/dS31zw

Die Idee ist es, die navbar Route mit einem Objekt zu liefern, die ein Etikett und eine Funktion hat (und was Sie wollen .. zB Icons.)

Als Bonus können Sie den Titel auch spritzen!

Hinweis: Dieser Trick hängt davon ab, dass componentWillMount() aufgerufen wird, bevor NavigationBarRouteMapper funktioniert. Wenn sich dies in Zukunft ändert, wird es definitiv brechen. Aber es funktioniert jetzt einwandfrei!

'use strict'; 

import React, {Component} from 'react'; 
import ReactNative from 'react-native'; 

const { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
    Navigator, 
    Alert, 
    TouchableHighlight 
} = ReactNative; 

class Home extends Component { 

    //This trick depends on that componentWillMount fires before the navbar is created 
    componentWillMount() { 
     this.props.route.navbarTitle = "Home"; 

     this.props.route.rightNavButton = { 
      text: "Button", 
      onPress: this._doSomething.bind(this) 
     }; 
    } 

    _doSomething() { 
    Alert.alert(
     'Awesome, eh?', 
     null, 
     [ 
     {text: 'Indeed'}, 
     ] 
    ) 
    } 

    render() { 
    return (
     <View style={styles.container}> 
      <Text>You are home</Text> 
     </View> 
    ); 
    } 
} 

class AppContainer extends Component { 

    renderScene(route, navigator) { 
     switch(route.name) { 
      case "Home": 
     //You must pass route as a prop for this trick to work properly 
      return <Home route={route} navigator={navigator} {...route.passProps} /> 
      default: 
      return (
     <Text route={route} 
     style={styles.container}> 
      Your route name is probably incorrect {JSON.stringify(route)} 
      </Text> 
    ); 
     } 
    } 

    render() { 
    return (
     <Navigator 
     navigationBar={ 
      <Navigator.NavigationBar 
      style={ styles.navbar } 
      routeMapper={ NavigationBarRouteMapper } /> 
     } 

     initialRoute={{ name: 'Home' }} 
     renderScene={ this.renderScene } 

     /> 
    ); 
    } 
} 

//Nothing fancy here, except for checking for injected buttons. 
var NavigationBarRouteMapper = { 
    LeftButton(route, navigator, index, navState) { 
    if(route.leftNavButton) { 
     return (
     <TouchableHighlight 
     style={styles.leftNavButton} 
     underlayColor="transparent" 
     onPress={route.leftNavButton.onPress}> 
      <Text style={styles.navbarButtonText}>{route.leftNavButton.text}</Text> 
     </TouchableHighlight> 
    ); 
    } 
    else if(route.enableBackButton) { 
     return (
     <TouchableHighlight 
     style={styles.leftNavButton} 
     underlayColor="transparent" 
     onPress={() => navigator.pop() }> 
      <Text style={styles.navbarButtonText}>Back</Text> 
     </TouchableHighlight> 
    ); 
    } 
    }, 
    RightButton(route, navigator, index, navState) { 
    if(route.rightNavButton) { 
     return (
     <TouchableHighlight 
     style={styles.rightNavButton} 
     underlayColor="transparent" 
     onPress={route.rightNavButton.onPress}> 
      <Text style={styles.navbarButtonText}>{route.rightNavButton.text}</Text> 
     </TouchableHighlight> 
    ); 
    } 
    }, 
    Title(route, navigator, index, navState) { 
    return (<Text style={styles.navbarTitle}>{route.navbarTitle || route.name}</Text>); 
    } 
}; 

var styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    justifyContent: 'center', 
    alignItems: 'center', 
    backgroundColor: '#F5FCFF', 
    marginTop: 66 
    }, 
    navbar: { 
    backgroundColor: '#ffffff', 
    }, 
    navbarTitle: { 
    marginVertical: 10, 
    fontSize: 17 
    }, 
    leftNavButton: { 
    marginVertical: 10, 
    paddingLeft: 8, 
}, 
    rightNavButton: { 
    marginVertical: 10, 
    paddingRight: 8, 
    }, 
    navbarButtonText: { 
    fontSize: 17, 
    color: "#007AFF" 
    } 
}); 

AppRegistry.registerComponent('AppContainer',() => AppContainer); 
+0

Schöne Lösung !! Ich habe mit genau diesem Problem eine Weile gekämpft. Vielen Dank für den Hinweis! Wie würden Sie eine erste Schaltfläche zuweisen? Sie injizieren Tasten pro Szene, aber ich möchte einen "Menü" Button von root zuweisen. – funkysoul

+0

@funkysoulzh Fügen Sie in der richtigen Methode in NavigationBarRouteMapper, zB LeftButton, Ihre if-condition-Klausel hinzu und fügen Sie die Schaltfläche darin hinzu. Genauso wie ich die Zurück-Schaltfläche in der LeftButton-Methode hinzufüge. In Ihrem Fall sollten Sie jedoch nach dem Namen der Route suchen. –

+0

Hey Ahmed, ich erkannte, dass meine Logik krumm war, da ich mit einer Anfangsszene anfange, kann ich auch die "anfänglichen" Knöpfe an diese Szene anhängen. Wenn man zu lange vor etwas sitzt, sieht man plötzlich nicht, wie einfach es ist ;-). Wie auch immer, danke für das oben genannte! – funkysoul