You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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接收navigation prop,无需额外调用useNavigation。

内容的提问来源于stack exchange,提问作者Ethan K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:37:23