如何禁用默认的BackHandler而不在个别场景中覆盖它?

时间:2018-05-22 02:48:20

标签: reactjs react-native navigation-drawer react-navigation react-native-router-flux

所以这是我正在使用的路线:

<Router>
                <Scene key="root" hideNavBar>
                    <Stack key="Auth" initial={!this.state.isLoggedIn}>
                        <Scene key="Login" hideNavBar component={Login} title="Login" />
                    </Stack>
                    <Stack key="Main" initial={this.state.isLoggedIn}>
                        <Scene drawer key="NavDrawer" hideNavBar contentComponent={() => <NavDrawer username={this.state.userName} />} type={ActionConst.REPLACE} panHandlers={null}>
                            <Scene key="homeTab" navBar={() => <PageHeader title='Home' />} drawerLockMode={'locked-closed'}>
                                <Scene tabs={true} tabBarComponent={ScrollableTabBar} tabBarPosition='top' lazy={true}>
                                    <Scene key="Home" hideNavBar component={Home} title={"Home"} name='Home'/>
                                </Scene>
                                <Scene key="itemDescription" hideNavBar component={itemDescription} title="Item Description" back />
                            </Scene>
                            <Scene key="helpTab" navBar={() => <PageHeader title='Help' />} title="Help" drawerLockMode={'locked-closed'}>
                                <Scene>
                                    <Scene key="Help" hideNavBar component={Help} title={"Help"} />
                                </Scene>
                            </Scene>
                            <Scene key="settingTab" navBar={() => <PageHeader title='Settings' />} title="Settings" drawerLockMode={'locked-closed'}>
                                <Scene>
                                    <Scene key="Setting" hideNavBar component={Setting} title={"Setting"} />
                                </Scene>
                            </Scene>
                            <Scene key="QRTab" navBar={() => <PageHeader title='QR Scanner' />} title="QR" drawerLockMode={'locked-closed'}>
                                <Scene>
                                    <Scene key="QRScanner" hideNavBar component={QRScanner} title={"QR Scanner"} />
                                </Scene>
                            </Scene>
                        </Scene>
                    </Stack>
                </Scene>
            </Router>

这是我NavDrawer的BackHandler:

handleBackButton() {
        if (Actions.currentScene === '_Home')
        this.onSignOut()
    else if (this.state.currentTab !== 'Home') {
        this.setState({ currentTab: 'Home' })
        Actions.homeTab();
    }
    else if (Actions.currentScene === 'Login')
    {
        BackHandler.exitApp();
    }
    else{
        Actions.pop();
    }
    return true;
}

componentDidMount() {
    BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}

componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress');
}

似乎RNRF抽屉已经为抽屉下任何新堆叠的场景实现了默认的BackHandler,默认行为为Actions.pop()

此时所有逻辑场景移动都按预期工作,但是,由于默认的BackHandler被调用而只是执行Actions.pop()以返回主页,因此选项卡突出显示不会移回Home,因为setState ({currentTab:'Home'})从未执行过。

有关如何禁用默认处理程序或在不将单个BackHandler添加到抽屉中的每个子场景的情况下执行变通方法的任何想法?

更新: 事实证明这个问题只发生在我自动登录时(即跳过Auth堆栈并直接进入Main堆栈),重新加载和componentWillUnmount之间似乎出错了componentDidMount没有被调用,而之前重新加载的BackHandler以某种方式发生冲突。

因为如果我尝试这种情况:

login --> Setting/Help/QR tab --> hardware back to Home它不会导致问题

但如果我这样做:

autoLogin(login using stored token) --> Setting/Help/QR tab --> hardware back to Home将调用默认的BackHandler,但是如果我再次按回,则会调用所需的BackHandler并且我已经注销,然后如果我再次尝试登录,则一切正常!

UPDATE2:

我现在可以确认问题在于热重新加载,当app重新加载时,componentWillUnmount从未被调用,并且当它被加载回来时,componentDidMount再次被调用,现在我们有2个BackHandler,处理相同的事件(我不知道它们在这种情况下应该如何表现,但这会导致使用Actions.pop()的处理程序而不是我定义的处理程序。

这就是为什么当我退出(并componentWillUnmount调用并删除BackHandler)并再次登录(然后通过componentDidMount在干净的平板上加载新的BackHandler)时一切正常。

现在我的新问题是,如果没有任何热重新加载并且用户只是关闭应用程序并再次打开它(当实际安装的应用程序没有像现在那样通过expo加载时)会导致问题吗?

1 个答案:

答案 0 :(得分:0)

在你的BackHandler eventlistener中尝试这个。请确保将其放在根组件中

let routeName = this.props.navigation.state.routeName // If you're using react navigation
let routeName = Actions.currentScene // If you're using router flux

BackHandler.addEventListener('hardwareBackPress', function() {

  if (routeName !== "Home") {
    this.props.navigation.goBack() // or create go back custom function 
    Actions.pop() // If your're using router flux
    return true;
  }
  return false;
});