Firebase 9 + React Context:如何限制未注册用户登录?
问题修复方案
你的问题核心是Context里的认证函数没有返回Promise,导致登录页面的await根本没等到Firebase的认证请求完成,不管请求成功失败,代码都会直接执行跳转逻辑。
第一步:修复Context中的认证函数
Firebase的createUserWithEmailAndPassword和signInWithEmailAndPassword本身返回Promise,但你的代码里没有把这个Promise返回出去,导致await无效。修改Context代码:
const UserContext = createContext(); export const AuthContextProvider = ({ children }) => { const [user, setUser] = useState({}); // 返回Firebase方法的Promise,让await可以等待 const createUser = (email, password) => { return createUserWithEmailAndPassword(authentication, email, password); }; // 同样返回Promise const signUser = (email, password) => { return signInWithEmailAndPassword(authentication, email, password); }; const logOut = () => { return signOut(authentication); }; useEffect(() => { const unsubscribe = onAuthStateChanged(authentication, (currenUser) => { setUser(currenUser); }); return () => { unsubscribe(); }; }, []); return ( <UserContext.Provider value={{ createUser, signUser, user, logOut }}> {children} </UserContext.Provider> ); }; export const UserAuth = () => { return useContext(UserContext); };
第二步:完善登录页面的错误处理
现在await会正确等待认证请求,只有成功时才跳转,失败时捕获错误并提示用户:
const SignIn = ({ navigation }) => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [showErr, setShowErr] = useState(''); const { user, signUser } = UserAuth(); const handleSignIn = async () => { setShowErr(''); // 清空之前的错误提示 try { // 等待认证请求完成 await signUser(email, password); // 仅当认证成功时跳转首页 navigation.navigate('Home'); } catch (e) { // 根据Firebase错误码给出针对性提示 switch(e.code) { case 'auth/user-not-found': setShowErr('该邮箱未注册,请先完成注册'); break; case 'auth/wrong-password': setShowErr('密码错误,请重试'); break; default: setShowErr('登录失败,请稍后再试'); } console.log(e.message); } }; return ( <View {...} > {/* 渲染错误提示 */} {showErr && <Text style={{color: 'red', marginTop: 10}}>{showErr}</Text>} </View> ); }; export default SignIn;
原理说明
Firebase的认证操作是异步的,必须返回它的Promise,await才能正确等待操作结果。之前的代码因为没有返回Promise,await signUser(...)会直接跳过等待执行跳转,此时Firebase的认证请求还在处理中,错误也无法被捕获。修改后,只有认证成功(Promise状态为resolved)才会跳转,失败时(Promise状态为rejected)会进入catch块处理错误,自然就能拦截未注册用户的登录请求。
内容的提问来源于stack exchange,提问作者BlackRain
相关产品推荐
相关产品推荐

