[英]Call a component function from react-native's Navigator buttons
我看到这个问题在非常不同的环境中四处徘徊,没有任何直接解决方案。 有人问我,我正在向我展示一些示例,说明如何使用导航执行我想要的代码,因为其中大多数已经采用了第三方解决方案,或者使用<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 />
,我们将希望能够从该组件活动实例共享状态/属性。 即使您在home组件中声明了onLeftPressed()
,执行上述代码也会导致错误,如下所示:
export default class Home extends Component {
onLeftPressed() {
console.log('Pressed left button')
}
render() {
return <View>
<Text>Home Component</Text>
</View>
}
}
所以眼前的问题是...如何从navigationBarRouteMapper
调用onRightPressed()
它实际上非常简单,虽然还有其他方法,例如在Router中注入组件,但是考虑到我的应用程序使用Redux
,将connect()
方法传递给Route对象有点麻烦。
因此,我想出了一个简单而有效的解决方案,无论您使用什么来管理状态,该解决方案都可以工作。 注射剂 。 没错,只需将您需要调用的内容直接插入到navigation
对象中即可。
可以通过this.props.navigator
从组件内部访问navigation
对象,这对我们来说是幸运的,Javascript对象是可变的,并通过引用自然传递。 这意味着我们对导航器对象所做的任何更改都将反映在注入到navigationBarRouteMapper
因此,首先让我们更改一些代码:
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>
}
}
您会注意到,我已经将onPress
值从{this.onLeftPressed.bind(this)}
更改为{navigator.__onLeftNavButtonPressed}
现在显然可以更改正在使用的名称,但是我喜欢双下划线前缀。
您还将看到我将标题更改为返回{navigator.navTitle || route.id}
{navigator.navTitle || route.id}
而不是route.id
,这意味着它将使用navigator中的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>
}
}
如您所见,唯一更改的是添加了一个constructor(...)
,该函数将函数和标题注入了navigator
对象。 现在,如果单击左按钮,将在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>
}
}
这会将一个事件注册到“向左/向右”按钮并设置Home组件的标题。 您也可以向Navigator对象中注入更多信息,例如,如果您想让__hasNavigationBar
函数返回true或false以隐藏整个导航栏,或者__rightNavButton
函数返回要在右侧按钮上显示的组件,只是一个TouchableOpacity按钮。
如前所述,还有其他方法可以做到这一点,但是考虑到我在应用程序中使用Redux似乎是最简单的方法,而我对此没有任何问题。
一种替代方法是使用事件总线,例如react-native-event-listeners。 我能够通过这种方式解决问题,并且比Hobbyist的解决方案简单得多。
基本上,它的工作方式是按钮将消息发送给接收方,然后接收方(在组件的上下文中)将执行必要的操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.