react-native 初始頁面新增雙擊退出,跳轉到其他頁面也觸發雙擊退出函式問題
阿新 • • 發佈:2019-02-05
今天在使用react-native BackHandler繫結雙擊退出時,遇到一個大坑,在使用react-navigation時,初始頁面繫結雙擊退出函式,在頁面解除安裝時刪除繫結函式,程式碼如下:
const lastBackPressed = Date.now();
export default class HomepageIndexPage extends Component{
...
//元件載入之後新增監聽
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.onBackPressed);
}
//元件解除安裝之前移除監聽
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.onBackPressed);
}
/* 再按一次退出函式,僅支援android */
_onBackPressed() {
if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
BackHandler.exitApp();
}
lastBackPressed = Date.now();
ToastAndroid.show('再按一次退出應用' , ToastAndroid.SHORT);
return true;
}
...
}
但當我從這個初始頁面,跳轉到其他頁面的時候,坑來了,點選Home建同樣會觸發,onBackPressed函式,提示 ‘再按一次退出應用’。並不是我預想的返回到上一個頁面,頓時一臉懵逼。這他媽是沒有觸發,componentWillUnmount函式啊!!!
左思右想,終於想明白了,這是因為,我們從初始頁面跳轉到其他頁面的時候,react-navigation把這個初始頁面存了起來,而不是把他銷燬掉,就像是路由跳轉的路線點一樣儲存起來,這樣我們在使用goBack()函式的時候才能回到上一個路由節點,知道了原因,也就好下手了,只要我們路由節點只有初始的一個的時候監聽雙擊退出函式,在多餘一個的時候刪除監聽的函式,就OK了。
現在我們需要找一個,只要路由變化就觸發的函式,而且在這個函式中能夠獲取到路由節點個數,這個函式就是 onNavigationStateChange 函式。這個函式是導航器所支援的是三個props之一(其餘兩個是ref和screenProps),以下是我的程式碼
const lastBackPressed = Date.now();
export default class HomepageIndexPage extends Component{
...
//元件載入之後新增監聽
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.onBackPressed);
}
//元件解除安裝之前移除監聽
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.onBackPressed);
}
/* 再按一次退出函式,僅支援android */
_onBackPressed() {
if (lastBackPressed && lastBackPressed + 2000 >= Date.now()) {
BackHandler.exitApp();
}
lastBackPressed = Date.now();
ToastAndroid.show('再按一次退出應用', ToastAndroid.SHORT);
return true;
}
render(){
return (
<View style={{flex:1}}>
<StackNavigation
screenProps={{isLogin:this.props.isLogin}}
ref={nav => { navigation = nav }}
onNavigationStateChange = {(prevState, newState, action) => {
if (newState.routes.length > 1) {
BackHandler.removeEventListener('hardwareBackPress', this.onBackPressed);
} else {
BackHandler.addEventListener('hardwareBackPress', this.onBackPressed);
}
}}
/ >
</View>
)
}
}
就這樣又踩過了一個坑!!!