react-navigation中DrawerNavigator自定义头部的两类问题咨询
嘿,我来帮你拆解这两个React Navigation的问题,顺便给你更优雅的解决方案~
首先,那个方案是针对React Navigation 1.x设计的,而v2版本对导航器的API和navigationOptions的处理逻辑做了不少改动,比如新增了defaultNavigationOptions来统一配置子页面的导航选项,旧的高阶组件包装方式自然就不兼容了。
其实你根本不需要这么复杂的包装逻辑,React Navigation 2已经提供了更简洁的方式给DrawerNavigator内的所有页面统一设置头部:直接在DrawerNavigator的配置里添加defaultNavigationOptions,它会被所有子页面继承,你只需要根据当前路由动态设置标题即可:
const HomeRouter = createDrawerNavigator( { Agenda: { screen: Agenda }, Nieuws: { screen: Nieuws }, // ...其他页面 }, { contentComponent: SideBar, drawerWidth: 300, // 统一设置所有子页面的头部 defaultNavigationOptions: ({ navigation }) => ({ header: <MenuHeader title={navigation.state.routeName} /> }) } );
另外你之前尝试在StackNavigator的screen中设置navigationOptions无效,是因为DrawerNavigator作为嵌套导航器,它的子页面的navigationOptions会优先于上层StackNavigator的配置,所以直接给DrawerNavigator设置defaultNavigationOptions才是正确的做法。
首先明确:ES模块是单例模式,你导入的组件和导出的确实是同一个实例,不存在引用不同的问题。出现这个错误的原因大概率是下面两种情况:
1. 循环引用问题
如果你的MenuHeader、Agenda、HomeRouter之间存在循环导入(比如MenuHeader里导入了HomeRouter处理导航逻辑,HomeRouter又导入了Agenda,Agenda又导入了MenuHeader),那么在模块加载时会出现暂时的未定义状态:当HomeRouter模块加载时,Agenda模块还没完全初始化完成,此时导入的Agenda是undefined,你尝试修改它的navigationOptions自然会抛出“Element type is invalid”的错误。
而在组件导出前设置navigationOptions,是在Agenda模块内部完成的,不会受到循环加载的影响,所以可以正常工作。
2. 配置时机问题
React Navigation在创建导航器(比如createStackNavigator)时,会立即读取对应screen组件的静态navigationOptions。如果你的代码逻辑中,先创建了导航器,再修改navigationOptions,那导航器不会识别到新的配置,但你的情况更可能是循环引用导致的。
解决方案
结合问题一的解决办法,你根本不需要在导入后修改navigationOptions——用DrawerNavigator的defaultNavigationOptions统一配置就可以避免所有重复代码和报错问题。如果一定要在外部设置,那需要先解决循环引用问题,比如把导航相关的逻辑抽离到独立的模块,避免互相导入。
内容的提问来源于stack exchange,提问作者Pieter van Oostrum

