react-navigation升级3.x 问题解决方案

背景

  • 最近把以前的RN项目更新了,react-native升级到了0.58,react-navigation升级到了3.3.0。
  • 咱们项目结构是TabNavigation,有A/B/C三个Tab,根据用户的权限来决定展现几个Tab,会有四种状况,ABC、AC、BC、C(C是一直存在的)。用createAppContainer建立了四个TabNavigation

升级

  • 按照旧版本的实现,建立三个StackNavigator,按照权限再建立四个TabNavigator,根据权限来决定展现哪一个。新版本升级后,统一使用createXXXNavigator生成,而后经过createAppContainer导出才行。

遇到的问题

  • 修改成新版本的写法后,发现进入二级页面tabbar不隐藏了,以前的参数无论用了。查阅文档后,官方给出了建议的写法:把TabNavigator当作StackNavigator的一部分,push时二级页面整个盖到TabNavigator上。reactnavigation.org/docs/en/nav…
  • 以前跳转二级页面时写的是this.props.navigation.navigate('XXX'),按照上面官方建议修改以后发现很差使了…缘由是this.props.navigation获取到的是当前页面的navigation,可是咱们外面包了一层TabNavigator,此时应该用TabNavigator的navigation去navigate('XXX')。好比页面A和页面B,在TabC上,在页面A上navigate('D'),可是页面A的StackNavigator里没有D哇,而且咱们要把Tab盖住哇,因此要用TabC的this.props.navigation去navigate('D')才能够。若是页面A的StackNavigator里有D,navigate时tabbar还会在,隐藏不了,就又回到了上一个问题。个人解决办法是:在跳转二级页面时发个通知,用TabC接收,而后再TabC里进行页面跳转。有点笨,可是想不到其它好办法了…
  • 还有就是安卓物理返回键的问题。这个问题真的很尴尬啊,在第一个Tab进二级页面,按返回键能够很棒的返回,然而在第二个和第三个Tab进二级页面后,按一下返回没反应,按两下就直接到第一个Tab了!!!Oh my god~~~~而后找解决方案,官方文档给出了reactnavigation.org/docs/en/cus…,我是想在一个地方写而后全局均可用,来来回试了不少次也没弄好,只能每一个页面都写了一次,具体实现看下面的代码。

具体实现

  1. 咱们项目结构是TabNavigation,有A/B/C三个Tab,根据用户的权限来决定展现几个Tab,会有四种状况,ABC、AC、BC、C(C是一直存在的)。用createAppContainer建立了四个TabNavigation
const ABCTabbar = createBottomTabNavigator({
    'ANav': {screen: ANav,},
    'BNav': {screen: BNav,},
    'CNav': {screen: CNav,},
});
const ACTabbar = createBottomTabNavigator({
    'ANav': {screen: ANav,},
    'CNav': {screen: CNav,},
});
const BCTabbar = createBottomTabNavigator({
    'BNav': {screen: BNav,},
    'CNav': {screen: CNav,},
});
const CTabbar = createBottomTabNavigator({
    'CNav': {screen: CNav,},
});

const ABCTabNavigator = createAppContainer(ABCTabbar);
const ACTabNavigator = createAppContainer(ACTabbar);
const BCTabNavigator = createAppContainer(BCTabbar);
const CTabNavigator = createAppContainer(CTabbar);
export { ABCTabNavigator, ACTabNavigator, BCTabNavigator, CTabNavigator };
复制代码
  1. 新建MainNavigation.js,在这个文件里判断用户有哪些权限,而后展现相应的TabNavigator
class MainNav extends Component {
	render() {
	  if (this.state.permission === 'ABC') {
	    return (<ABCTabNavigator/>);
	  } else if (this.state.permission == 'AC') {
	    return (<ACTabNavigator/>);
	  } else if (this.state.permission == 'BC') {
	    return (<BCTabNavigator/>);
	  } else {
	    return (<CTabNavigator/>);
	  }
	}
}
复制代码
  1. 在MainNavigation.js里,生成一个MainNavigation,在入口render里配置成就OK了
const Main = createStackNavigator({
    MainNav: {screen: MainNav},
    DPage: {screen: DPage},
});
const MainNavigation = createAppContainer(Main);
export default MainNavigation;
复制代码
  1. 安卓物理返回键问题。从网上找了个工具类AndroidBackAction.js,修改了一下
import {BackHandler} from 'react-native';

const handleAndroidBackButton = callback => {
  BackHandler.addEventListener('hardwareBackPress', callback);
};

const removeAndroidBackButtonHandler = (callback) => {
  BackHandler.removeEventListener('hardwareBackPress', callback);
}

export {handleAndroidBackButton, removeAndroidBackButtonHandler};
复制代码

页面上的实现:html

import {handleAndroidBackButton, removeAndroidBackButtonHandler} from '../../Util/AndroidBackAction.js'; 	// 你本身的路径

export default class D extends Component {

    constructor(props) {
        super(props);
        handleAndroidBackButton(this.onBackAndroid);	// 必定要在这里写
    }

    componentWillUnmount() {
        removeAndroidBackButtonHandler(this.onBackAndroid);	// 必定要在这里写
    }

    onBackAndroid = () => {
        this.props.navigation.goBack();
        return true;
    };
}

复制代码

还有个按两下退出应用的,我是写在了入口的地方(就配置的地方),监听的方式是同样的,就是onBackAndroid实现不同react

onBackAndroid = () => {
    if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
        //最近2秒内按过back键,能够退出应用。
        return false;
    }
    this.lastBackPressed = Date.now();
    ToastAndroid.show('再按返回退出应用', ToastAndroid.SHORT);
    return true;
};
复制代码

好啦,大功告成~~~android

结束~撒花~~~react-native

相关文章
相关标签/搜索