Javascript 反应本机:将场景绑定到导航栏

Javascript 反应本机:将场景绑定到导航栏,javascript,react-native,navigator,Javascript,React Native,Navigator,我正在组装这个问答应用程序,遇到了一个障碍: 我想从导航栏触发场景中的一个函数。与登录应用程序类似,我在导航栏中有一个按钮用于提交答案: RightButton(route, navigator, index, navState) { if (route.name=='TextInputView'){ return <TouchableHighlight underlayColor="transparent" style

我正在组装这个问答应用程序,遇到了一个障碍:

我想从导航栏触发场景中的一个函数。与登录应用程序类似,我在导航栏中有一个按钮用于提交答案:

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>
    }
right按钮(路线、导航器、索引、导航状态){
if(route.name='TextInputView'){
返回此.refs.TextInputView.submitSolution()}>
多恩
}
renderscene(路线、导航器)如下所示:

if (route.name == 'TextInputView'){
  return <TextInputView ref="TextInputView" navigator={navigator} {...route.passProps}/>
}
if(route.name==“TextInputView”){
返回
}
当然,在“TextInputView”组件中,我有一个“submitSolution”函数

问题是如果我在现场并按下“完成”-我总是得到: “undefined不是对象(计算'\u this2.refs.TextInputView')


一如既往:感谢您的帮助

好吧,您可以通过将与提交相关的所有内容保留在场景本身中来完成

怎么做

您可以按需在导航栏中插入一个按钮

以下是我为正在进行的项目创建的解决方案:

其思想是为导航栏路线提供一个具有标签和功能的对象(以及您喜欢的任何对象,例如图标)

作为奖励,您也可以插入标题

注意:这个技巧取决于在NavigationBarRouteMapper工作之前调用componentWillMount()。如果将来发生此更改,它肯定会破坏它。但是现在它可以完美地工作了

'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);
“严格使用”;
从“React”导入React,{Component};
从“react native”导入ReactNative;
常数{
评估学,
样式表,
文本,
看法
领航员,
警觉的,
可触摸高光
}=反应性;
类Home扩展组件{
//这个技巧取决于组件将在创建导航栏之前触发
组件willmount(){
this.props.route.navbartile=“Home”;
this.props.route.rightNavButton={
文字:“按钮”,
onPress:这个。绑定(这个)
};
}
_doSomething(){
警惕,警惕(
“太棒了,是吗?”,
无效的
[
{文本:'确实'},
]
)
}
render(){
返回(
你到家了
);
}
}
类AppContainer扩展组件{
renderScene(路线、导航器){
交换机(路由名称){
案例“家”:
//你们必须通过路线作为道具,这个技巧才能正常工作
返回
违约:
返回(
您的路由名称可能不正确{JSON.stringify(route)}
);
}
}
render(){
返回(
);
}
}
//这里没有什么特别的,除了检查注入的按钮。
变量NavigationBarRouteMapper={
LeftButton(路线、导航器、索引、导航状态){
if(route.leftNavButton){
返回(
{route.leftNavButton.text}
);
}
else if(route.enableback按钮){
返回(
navigator.pop()}>
返回
);
}
},
右按钮(路线、导航器、索引、导航状态){
if(路由右导航按钮){
返回(
{route.rightNavButton.text}
);
}
},
标题(路线、导航器、索引、导航状态){
返回({route.navbartile | | route.name});
}
};
var styles=StyleSheet.create({
容器:{
弹性:1,
为内容辩护:“中心”,
对齐项目:“居中”,
背景颜色:“#F5FCFF”,
玛金托普:66
},
导航栏:{
背景颜色:“#ffffff”,
},
navbarTitle:{
玛吉:10,
尺码:17
},
左导航按钮:{
玛吉:10,
paddingLeft:8,
},
右导航按钮:{
玛吉:10,
paddingRight:8,
},
navbarButtonText:{
尺寸:17,
颜色:“007AFF”
}
});
AppRegistry.registerComponent('AppContainer',()=>AppContainer);

Nice solution!!已经为此奋斗了一段时间。非常感谢您的提示!您将如何分配初始按钮?您将为每个场景注入按钮,但我想分配一个“菜单”button from root.@funkysoulzh在NavigationBarRouteMapper内的正确方法中,例如LeftButton,添加if条件子句并在其中添加按钮。就像我在LeftButton方法中添加back按钮一样。但在你的例子中,你可能需要检查路线名称。嘿,艾哈迈德,我意识到我的逻辑是错误的,因为我从一个初始场景开始,我还可以将“初始”按钮附加到该场景。当你坐在某物前太久时,你突然看不到它有多么容易;-)。无论如何,谢谢你的上述建议@那也行,哈哈!很高兴能帮上忙。