React Native中如何从嵌套StackNavigator打开侧边菜单?
看了你的导航结构——顶层是包含登录、重置密码、Dashboard等页面的StackNavigator,同时还有一个DrawerNavigator(RootDrawer)管理侧边栏菜单。要在嵌套的Stack页面里调出侧边菜单,这里有几个实用方案:
方案1:直接调用Drawer的打开方法(适配层级较浅的嵌套)
如果你的RootDrawer是顶层导航,而StackNavigator嵌套在RootDrawer的某个页面里(比如DashboardScreen内部是个Stack),那在Stack的子页面里,你可以通过获取父级Drawer的navigation对象来触发菜单:
// 在Stack页面的按钮或headerLeft里实现打开逻辑 const openSideMenu = () => { // 获取Drawer的navigation上下文 const drawerNav = navigation.dangerouslyGetParent(); drawerNav?.openDrawer(); };
比如在页面的导航配置里添加菜单按钮:
static navigationOptions = ({ navigation }) => ({ headerLeft: () => ( <TouchableOpacity onPress={() => { const drawerNav = navigation.dangerouslyGetParent(); drawerNav.openDrawer(); }}> <Icon name="menu" style={{ marginLeft: 15 }} /> </TouchableOpacity> ), });
方案2:用dispatch发送Drawer动作(适配深层嵌套)
要是嵌套层级较深,直接获取父级navigation比较麻烦,那就用DrawerActions发送打开指令,这种方式不依赖层级结构:
首先导入对应的action:
import { DrawerActions } from 'react-navigation-drawer';
然后在需要打开菜单的地方调用:
const openSideMenu = () => { navigation.dispatch(DrawerActions.openDrawer()); };
同样可以把这个方法绑定到headerLeft或者页面内的自定义按钮上,用法和上面一致。
方案3:调整导航结构(从根源避免嵌套问题)
有时候嵌套混乱才是问题的根源,建议把DrawerNavigator作为顶层导航,然后把需要嵌套Stack的页面(比如Dashboard+VehicleDetails)整合成一个独立Stack,再放到Drawer里。这样Stack里的所有页面都能直接调用打开方法,不用绕弯子:
调整后的代码示例:
// 先定义Dashboard相关的子Stack const DashboardStack = StackNavigator({ DashboardHome: { screen: DashboardScreen }, VehicleDetails: { screen: VehicleDetailsScreen }, // 其他需要嵌套的Stack页面... }); // 再定义DrawerNavigator,把整个子Stack作为一个选项 const RootDrawer = DrawerNavigator({ Dashboard: { screen: DashboardStack, // 用整个Stack代替单个页面 navigationOptions: { drawerLabel: 'Dashboard', drawerIcon: () => ( <Icon name="home" style={styles.drawerIconStyle} /> ), }, }, VehicleEnquiry: { screen: VehicleEnquiryScreen, navigationOptions: { drawerLabel: 'Barcode Scanner', drawerIcon: () => ( <Icon name="barcode" style={styles.drawerIconStyle} /> ), }, }, Logout: { screen: LoginScreen, navigationOptions: { title: "Login", drawerLabel: 'Logout', drawerIcon: () => ( <Icon name="arrow-left" style={styles.drawerIconStyle} /> ), headerLeft: null }, }, }); // 最后把登录相关页面和Drawer整到顶层Stack里 const AppRootStack = StackNavigator({ Login: { screen: LoginScreen }, PasswordReset: { screen: PasswordResetScreen }, MainApp: { screen: RootDrawer }, });
这样调整后,DashboardStack里的任何页面,直接写navigation.openDrawer()就能打开侧边菜单了,省心很多。
版本兼容提醒
要是你用的是react-navigation v5+版本,API会略有不同,需要用useNavigation钩子获取导航对象:
import { useNavigation } from '@react-navigation/native'; import { DrawerActions } from '@react-navigation/drawer'; const VehicleDetailsScreen = () => { const navigation = useNavigation(); const openSideMenu = () => { navigation.dispatch(DrawerActions.openDrawer()); }; return ( <TouchableOpacity onPress={openSideMenu}> <Icon name="menu" /> </TouchableOpacity> ); };
内容的提问来源于stack exchange,提问作者Razem Ponad-kilo

