React Navigation抽屉退出按钮失效:报undefined is not a function错误
问题分析与解决方案
你的问题核心是导航上下文隔离导致跳转失败:你在Home.js中多次使用NavigationContainer independent={true}创建了独立的导航容器,这些容器和App.js中的根导航上下文完全隔离,导致抽屉里的导航实例无法找到根Stack中的LogIn路由;同时自定义抽屉内容中错误地使用了useNavigation而非抽屉传递的navigation props,进一步引发函数未定义错误。
修复步骤
1. 重构导航结构,统一上下文
将抽屉导航作为App.js根Stack中Home屏幕的子导航,移除所有多余的NavigationContainer,只保留App.js中的根容器。
2. 修改HomeScreen.js(原Home.js)
import React, { useState } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, Alert } from 'react-native'; import { createDrawerNavigator, DrawerContentScrollView, DrawerItemList, DrawerItem } from '@react-navigation/drawer'; import { getAuth, signOut } from 'firebase/auth'; const Drawer = createDrawerNavigator(); const auth = getAuth(); // 自定义抽屉内容:直接使用props传递的navigation const CustomDrawerContent = (props) => { const handleSignOut = () => { signOut(auth) .then(() => { // 获取根导航上下文,跳转到LogIn页面 props.navigation.getParent().replace('LogIn'); }) .catch((error) => Alert.alert('Error', error.message)); }; return ( <DrawerContentScrollView {...props}> <DrawerItemList {...props} /> <DrawerItem label="Sign Out" onPress={handleSignOut} /> </DrawerContentScrollView> ); }; // 主页内容组件 const HomeContent = () => { const [hours, setHours] = useState(0); const increaseHours = () => setHours(hours + 1); const decreaseHours = () => hours > 0 && setHours(hours - 1); return ( <SafeAreaView style={styles.container}> <View style={styles.content}> <Text>Email: {auth.currentUser?.email}</Text> <Text style={styles.hoursText}>Total Hours: {hours}</Text> <TouchableOpacity style={styles.button} onPress={increaseHours}> <Text style={styles.buttonText}>Add Hour</Text> </TouchableOpacity> <TouchableOpacity style={styles.button} onPress={decreaseHours}> <Text style={styles.buttonText}>Remove Hour</Text> </TouchableOpacity> </View> </SafeAreaView> ); }; // 抽屉导航作为HomeScreen导出 export default function HomeScreen() { return ( <Drawer.Navigator drawerContent={(props) => <CustomDrawerContent {...props} />}> <Drawer.Screen name="Home" component={HomeContent} /> </Drawer.Navigator> ); } const styles = StyleSheet.create({ container: { flex: 1 }, content: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, hoursText: { fontSize: 20, marginBottom: 20 }, button: { backgroundColor: '#2196f3', padding: 10, borderRadius: 5, marginBottom: 10, }, buttonText: { color: '#fff', fontSize: 16, fontWeight: 'bold' }, });
3. 确保App.js导入正确
确认App.js中导入的HomeScreen路径和文件名一致(如果原文件是Home.js,建议重命名为HomeScreen.js避免混淆)。
关键修改说明
- 移除所有
NavigationContainer independent={true}:根导航上下文统一由App.js中的容器提供,所有子导航共享该上下文。 - 使用
props.navigation.getParent():抽屉导航是根Stack的子导航,通过getParent()获取根导航实例,才能正确跳转到根Stack中的LogIn路由。 - 自定义抽屉内容直接使用
props.navigation:抽屉组件会自动从Drawer.Navigator接收navigationprop,无需额外调用useNavigation。
内容的提问来源于stack exchange,提问作者Ethan K
相关产品推荐
相关产品推荐

