[英]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.