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

React项目中useSignInWithEmailAndPassword未抛出正确Firebase错误

问题分析与解决方案

核心问题

  1. API使用错误:react-firebase-hooks提供的signInWithEmailAndPassword函数不返回Promise,你写的.then()和.catch()会直接执行,不会等待鉴权结果,这就是为什么无论输入是否正确都会进入.then()分支。
  2. 逻辑冗余且不严谨:用登录接口判断邮箱是否已存在完全没必要——Firebase注册接口本身会在邮箱已被使用时抛出明确错误,且你把wrong-password错误直接等同于“邮箱已存在”的逻辑不严谨(邮箱未注册时会返回user-not-found错误,和密码错误是不同场景)。

正确实现方式

直接调用注册接口createUserWithEmailAndPassword,利用react-firebase-hooks提供的状态捕获错误即可:

import { AuthModalState } from '@/atoms/authModalAtom';
import { Input, Button, Flex, Text } from '@chakra-ui/react';
import React, { useState, useEffect } from 'react';
import { useSetRecoilState } from 'recoil';
import { useCreateUserWithEmailAndPassword } from "react-firebase-hooks/auth"
import { auth } from '@/firebase/clientApp';
import 'firebase/auth';

const SignUp: React.FC = () => {
    
    const setAuthModalState = useSetRecoilState(AuthModalState)
    const [signUpForm, setSignUpForm] = useState({
        email:"",
        password: "",
        confirmPassword: "",
    })
    const [notMatchedError, setNotMatchedError] = useState("")
    const [alreadyInUseError, setAlreadyInUseError] = useState("")
    
    const [
        createUserWithEmailAndPassword,
        user,
        loading,
        userError,
    ] = useCreateUserWithEmailAndPassword(auth);
    
    // 监听注册错误状态
    useEffect(() => {
        if (userError) {
            switch(userError.code) {
                case 'auth/email-already-in-use':
                    setAlreadyInUseError("该邮箱已被注册");
                    break;
                case 'auth/invalid-email':
                    setAlreadyInUseError("邮箱格式无效");
                    break;
                case 'auth/weak-password':
                    setAlreadyInUseError("密码强度不足");
                    break;
                default:
                    setAlreadyInUseError(userError.message);
            }
        }
    }, [userError])
    
    const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
        event.preventDefault()
        setNotMatchedError("");
        setAlreadyInUseError("");
        
        if (signUpForm.password !== signUpForm.confirmPassword) {
            setNotMatchedError("两次输入的密码不一致");
            return; // 密码不匹配时终止后续流程
        }
        
        // 调用Firebase注册接口
        createUserWithEmailAndPassword(signUpForm.email, signUpForm.password);
        
        // 注册成功后的处理(比如关闭模态框)
        if (user && !loading) {
            setAuthModalState({ open: false });
        }
    }
    
    return (
        <Flex direction="column" gap={4} p={4}>
            <Input
                type="email"
                value={signUpForm.email}
                onChange={(e) => setSignUpForm({...signUpForm, email: e.target.value})}
                placeholder="请输入邮箱"
            />
            <Input
                type="password"
                value={signUpForm.password}
                onChange={(e) => setSignUpForm({...signUpForm, password: e.target.value})}
                placeholder="请输入密码"
            />
            <Input
                type="password"
                value={signUpForm.confirmPassword}
                onChange={(e) => setSignUpForm({...signUpForm, confirmPassword: e.target.value})}
                placeholder="请确认密码"
            />
            {notMatchedError && <Text color="red.500" fontSize="sm">{notMatchedError}</Text>}
            {alreadyInUseError && <Text color="red.500" fontSize="sm">{alreadyInUseError}</Text>}
            <Button isLoading={loading} colorScheme="blue" onClick={onSubmit}>
                注册
            </Button>
        </Flex>
    )
}

export default SignUp;

关键修改说明

  • 移除无用的useSignInWithEmailAndPassword,直接通过注册接口完成流程
  • 利用react-firebase-hooks返回的userError状态自动捕获注册错误,无需手动处理Promise
  • 补充密码不匹配时的终止逻辑,避免无效调用
  • 针对常见错误码做友好提示,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:40:22