React Native+Firebase双角色登录失败及角色导航跳转求助
问题解决方案
一、修复登录失败问题
你的登录代码存在两个关键问题:
- 未定义
email和password状态:handleSignIn里用到的账号密码变量没有在组件内声明状态,无法获取用户输入内容。 - 缺少Firebase基础配置验证:需确认已在项目中正确初始化Firebase,且控制台「Authentication」模块已启用「邮箱/密码」登录方式。
修改后的SignIn组件代码:
import { useState } from 'react'; import { View, TextInput, Button, Alert } from 'react-native'; import { auth, db } from '../firebase/config'; // 替换为你的Firebase配置路径 const SignIn = ({ navigation }) => { // 新增账号密码状态管理 const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [user, setUser] = useState(null); const handleSignIn = async () => { try { // 校验输入合法性 if (!email || !password) { Alert.alert('提示', '请输入完整的邮箱和密码'); return; } // 执行Firebase登录 const userCredentials = await auth.signInWithEmailAndPassword(email, password); const user = userCredentials.user; console.log('登录成功:', user.email); // 获取用户角色并跳转对应页面 const userDoc = await db.collection('users').doc(user.uid).get(); const userData = userDoc.data(); setUser(userData); // 根据角色跳转至专属导航首页 if (userData?.role === 'admin') { navigation.replace('AdminNavi'); } else { navigation.replace('UserNavi'); } } catch (error) { // 更明确的错误提示,便于排查问题 Alert.alert('登录失败', error.message); console.error('登录错误详情:', error.code, error.message); } }; return ( <View style={{ padding: 20, gap: 15 }}> <TextInput placeholder="邮箱" value={email} onChangeText={setEmail} keyboardType="email-address" autoCapitalize="none" /> <TextInput placeholder="密码" value={password} onChangeText={setPassword} secureTextEntry /> <Button title="登录" onPress={handleSignIn} /> </View> ); }; export default SignIn;
二、配置角色自动跳转导航
之前的导航逻辑错误,不能在useEffect中直接渲染导航组件,需在App.js中统一管理用户状态和导航渲染,同时调整AdminNavi和UserNavi的结构,移除已登录状态下不需要的Auth页面。
1. 调整导航组件(移除Auth页面)
修改AdminNavi:
import { DrawerNavigator } from '@react-navigation/drawer'; import AdminTabs from './AdminTabs'; import StackNavigator from './StackNavigator'; import DrawerContent from './DrawerContent'; const Drawer = DrawerNavigator; const AdminNavi = () => { return ( <Drawer.Navigator screenOptions={{ headerShown: false }} drawerContent={(props) => <DrawerContent {...props} />} > {/* 已登录用户无需访问登录页面,移除Auth */} <Drawer.Screen name="AdminTabs" component={AdminTabs} /> <Drawer.Screen name="Stack" component={StackNavigator} /> </Drawer.Navigator> ); }; export default AdminNavi;
修改UserNavi:
import { DrawerNavigator } from '@react-navigation/drawer'; import Tabs from './Tabs'; import StackNavigator from './StackNavigator'; import DrawerContent from './DrawerContent'; const Drawer = DrawerNavigator; const UserNavi = () => { return ( <Drawer.Navigator screenOptions={{ headerShown: false }} drawerContent={(props) => <DrawerContent {...props} />} > {/* 已登录用户无需访问登录页面,移除Auth */} <Drawer.Screen name="Tabs" component={Tabs} /> <Drawer.Screen name="Stack" component={StackNavigator} /> </Drawer.Navigator> ); }; export default UserNavi;
2. 重构App.js,实现全局状态监听和导航切换
import { useState, useEffect } from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import { auth, db } from './firebase/config'; // 替换为你的Firebase配置路径 import SignIn from './screens/SignIn'; import AdminNavi from './navigators/AdminNavi'; import UserNavi from './navigators/UserNavi'; const Stack = createStackNavigator(); const App = () => { const [currentUser, setCurrentUser] = useState(null); const [userRole, setUserRole] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { // 监听Firebase用户登录状态变化 const unsubscribe = auth.onAuthStateChanged(async (user) => { setLoading(true); if (user) { // 从Firestore获取用户角色数据 const userDoc = await db.collection('users').doc(user.uid).get(); const data = userDoc.data(); setCurrentUser(user); setUserRole(data?.role); } else { setCurrentUser(null); setUserRole(null); } setLoading(false); }); // 组件卸载时清理监听 return () => unsubscribe(); }, []); // 加载状态处理(可替换为自定义加载组件) if (loading) { return null; } return ( <NavigationContainer> <Stack.Navigator screenOptions={{ headerShown: false }}> {!currentUser ? ( // 未登录时显示登录页面 <Stack.Screen name="SignIn" component={SignIn} /> ) : userRole === 'admin' ? ( // 管理员登录后显示专属导航 <Stack.Screen name="AdminNavi" component={AdminNavi} /> ) : ( // 普通用户登录后显示专属导航 <Stack.Screen name="UserNavi" component={UserNavi} /> )} </Stack.Navigator> </NavigationContainer> ); }; export default App;
额外注意事项
- 确保Firestore的
users集合中,每个用户文档都包含role字段(值为admin或client),否则无法正确判断角色。 - 如需添加登出功能,在导航的
DrawerContent中添加登出按钮,调用auth.signOut()即可触发状态监听,自动返回登录页面。
内容的提问来源于stack exchange,提问作者Mohsen Mohsen
相关产品推荐
相关产品推荐

