1. 程式人生 > >react-native 初始頁面新增雙擊退出,跳轉到其他頁面也觸發雙擊退出函式問題

react-native 初始頁面新增雙擊退出,跳轉到其他頁面也觸發雙擊退出函式問題

今天在使用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>
    )
  }
}

就這樣又踩過了一個坑!!!