如何将navigator对象传递给react natives根文件中使用的组件?

时间:2016-09-27 14:31:14

标签: reactjs react-native react-native-android

以下是我的应用组件:

/**
 * Class app from where the app bootstraps
 */
export default class App extends Component {
  constructor(props) {
    super(props);
  }

  // This is where all your routes will be processed
  renderScene(route, navigator) {
    // Set a variable to get the route
    let RouteComponent = route.component;

    _navigator = navigator;

    // With props return the components
    return (
      <RouteComponent navigator={navigator} {...route.passProps} />
    );
  }

  static navigationBarRouteMapper = openControlPanel => ({
      LeftButton: function(route, navigator, index, navState) {
        return (

          // Hamburger icon which on clicked opens the menu
          <TouchableOpacity style={navBarStyle.left} onPress={() => openControlPanel()}>
            <View>
              {hamburgerIcon}
            </View>
          </TouchableOpacity>
        );
      },
      RightButton: function(route, navigator, index, navState) {
        return (
          // cart menu
          <TouchableWithoutFeedback onPress={() => dismissKeyboard()}>
            <View style={navBarStyle.right}>
              {cartIcon}
              <View style={navBarStyle.counter}>
                <Text style={navBarStyle.counterText}>20</Text>
              </View>
            </View>
          </TouchableWithoutFeedback>
        );
      },
      Title: function(route, navigator, index, navState) {
        // Title of the route
        return (
          <TouchableWithoutFeedback onPress={() => dismissKeyboard()}>
            <View style={navBarStyle.titleWrap}>
              <Text style={navBarStyle.title}>{route.title.toUpperCase()}</Text>
            </View>
          </TouchableWithoutFeedback>
        );
      }
  })

  // Close the menu drawer
  closeControlPanel() {
    this._drawer.close();
  }

  // open the menu drawer
  openControlPanel() {
    this._drawer.open();
    dismissKeyboard();
  }

  // On clicking the menu item, this function routes to that menu item page
  getNavigator(route) {
    this.refs.navigator.replace(route);
    this.closeControlPanel();
  }

  render() {

    return (
      <Drawer
        ref={ (ref) => { this._drawer = ref; } }
        type="overlay"
        content={<Menu navigator={this.getNavigator.bind(this)} menuItems={menu} closeControlPanel={this.closeControlPanel.bind(this)} />}
        onOpenStart={() => dismissKeyboard()}
        tapToClose={true}
        openDrawerOffset={0.2}
        panCloseMask={0.2}
        panOpenMask={20}
        acceptPan={true}
        closedDrawerOffset={-3}
        styles={drawerStyle}
        tweenHandler={(ratio) => ({

          // This code will maintain the opacity for main
          // Whilst the opacity for the mainOverlay on the screen will be faded.
          main: { opacity: 1 },
          mainOverlay: {
            opacity: ratio / 2,
            backgroundColor: 'black',
          }

        })}>

        <Navigator
          initialRoute={homeScene}
          renderScene={this.renderScene}
          ref="navigator"
          // Navbar of the app
          navigationBar={
            <Navigator.NavigationBar
              routeMapper={App.navigationBarRouteMapper(this.openControlPanel.bind(this))}
              style={navBarStyle.navBar}
            />
          }
        />

        <EditSearch />
      </Drawer>
    );
  }
}

在最底部,您会看到包含两个文本输入的<EditSearch>组件。除主页外,该组件对于应用程序中的所有页面都是通用的。

因此,我想知道我目前在哪个页面或场景,以便我可以检查场景/页面是否是主页。如果它是主页,我会隐藏组件,否则我会为所有其他页面显示它。

我尝试通过ref传递导航器,如下所示:

<EditSearch nav={this.refs.navigator} />

但是,我在<EditSearch>组件上未定义,并且当页面发生更改时视图不会重新呈现,因为它没有检测到任何状态更改。

我可以做类似的事情:

this.state = {
  currentRoute: 'home'
}

然后在路线更改时更改此状态。但是,我无法在renderScene中更改状态,因为renderScene中的设置状态将导致无限循环。如果我可以在路由更改时将此状态设置为页面标题,那么我可以将该状态发送到<EditSearch>组件。

我很困惑如何将当前路由信息传递给此公共组件。感谢您的期待。

2 个答案:

答案 0 :(得分:0)

好的,我找到了一个解决方案,但我不确定它是否合适。

以下是我的解决方案。

首先,我创建了状态和函数来设置该状态:

  constructor(props) {
    super(props);

    this.state = {
      isHome: false
    };

    this.setIsHome = this.setIsHome.bind(this);
  }

  setIsHome(flag) {
    // Set state to let component know whether the page is home or not
    this.setState({
      isHome: flag ? flag : false
    });
  }

然后将该函数传递给那些页面可以隐藏或显示<EditSearch>组件的所有页面:

<RouteComponent navigator={navigator} {...route.passProps} setIsHome={this.setIsHome} />

然后我将isHome状态传递给<EditSearch>组件:

<EditSearch isHome={ this.state.isHome } />

这就是我在家庭组件中调用该函数的方式:

  componentWillMount() {
    this.props.setIsHome(true);
  }

  componentWillUnmount() {
    this.props.setIsHome(false);
  }

这是我显示/隐藏组件的方式。我希望它有所帮助。但是,知道如何将导航器对象传递给这些组件会非常好。

答案 1 :(得分:0)

这是Drawer Github问题的解决方案。

  

为此找到了一个快速的解决方法,但它并不理想。如果你包装   导航器与抽屉组件,然后在内部   Navigator.NavigationBar你可以设置this.navigator = this.navigator ||   导航器,然后您可以将导航器传递给您的内容   抽屉的组件。

<Drawer
  content={<Main navigator={this.navigator}/>}
  type='overlay'>

  <Navigator
    renderScene={renderScene}
    navigationBar={

      <Navigator.NavigationBar
        routeMapper={{
          LeftButton: (route, navigator, index, navState) => {

            this.navigator = this.navigator || navigator;

            return (
              <View>
                <Text>Something</Text>
              </View>
            );
          }
        }}
      />
  />
</Drawer>

https://github.com/root-two/react-native-drawer/issues/187#issuecomment-231461585