使用React+Formik+Yup实现Firebase登录时出现POST 400错误
问题及解决方案
问题描述
- 登录功能验证测试后控制台出现POST 400错误,密码仅设置了最小/最大字符数校验规则,结果不符合预期。
- 登录成功后需要实现重定向到首页的逻辑。
- 登录失败时,需区分场景:用户不存在时抛出警告,其他错误场景抛出错误提示。
相关代码
LoginForm组件代码
import React from "react"; import { View, TextInput, TouchableOpacity,Text } from "react-native"; import { Formik, Form, Field, ErrorMessage } from 'formik'; import * as Yup from 'yup'; import RegisterForm from "./RegisterForm"; import {Link} from "react-router-dom"; import auth from "../../firebaseConfig"; import {signInWithEmailAndPassword} from "firebase/auth"; import Login from "../../firebaseConfig"; const SignupSchema = Yup.object().shape({ email: Yup.string().email('El email ingresado no es valido.').required('Por favor ingrese su email.'), contraseña: Yup.string() .min(6, 'La contraseña es muy corta.') .max(20, 'La contraseña es demasiado larga.') .required('Por favor ingrese su contraseña.') }); export default function LoginForm () { return( <Formik initialValues={{ email: '', contraseña: '' }} validationSchema={SignupSchema} onSubmit={values=> Login(values)} > {({values,errors,touched, handleChange, setFieldTouched, isValid, handleSubmit}) =>( <View> <TextInput placeholder="Email" value={values.email} onChangeText={handleChange('email')} onBlur={()=> setFieldTouched('email')}/> {touched.email && errors.email && ( <Text>{errors.email}</Text> )} <TextInput placeholder="Contraseña" value={values.contraseña} onChangeText={handleChange('contraseña')} onBlur={()=> setFieldTouched('contraseña')} secureTextEntry={true}/> {touched.contraseña && errors.contraseña && ( <Text>{errors.contraseña}</Text> )} <TouchableOpacity disabled={!isValid} style={{backgroundColor: isValid? '#289D8C': '#808080'}} onPress={handleSubmit}> <Text>Ingresar</Text> </TouchableOpacity> <Link to="/RegisterForm" exact component={<RegisterForm/>} >¿No estás registrado?</Link> </View> )} </Formik> ) }
firebaseConfig.js代码
import { getAnalytics } from "firebase/analytics"; import { initializeApp } from 'firebase/app'; import { getFirestore } from "firebase/firestore"; //import firebase from 'firebase/compat/app'; import 'firebase/compat/auth'; import 'firebase/compat/firestore'; import { getAuth, signInWithEmailAndPassword } from "firebase/auth"; const firebaseConfig = { apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", authDomain: "XXXXXXXXXXXXXXXXXXX", projectId: "XXXXXXXXXXXXXXXXXXXX", storageBucket: "XXXXXXXXXXXXXXXXXXXXXXXXXXXX", messagingSenderId: "XXXXXXXXXXXX", appId: "--------------------------------", measurementId: "-------------" }; const app = initializeApp(firebaseConfig); const db = getFirestore(app); const analytics = getAnalytics(app); /* provider.setCustomParameters({ prompt: 'select_account' }); */ /* const provider = new GoogleAuthProvider(); */ const auth = getAuth(); export { auth, db }; export default function Login({email, contraseña}) { const auth = getAuth(); signInWithEmailAndPassword(auth, email, contraseña) .then((userCredential) => { // Signed in const user = userCredential.user; // ... }) .catch((error) => { const errorCode = error.code; const errorMessage = error.message; }); } /* auth.languageCode = 'it'; provider.setCustomParameters({ 'login_hint': 'user@example.com' }); signInWithPopup(auth, provider) .then((result) => { const credential = GoogleAuthProvider.credentialFromResult(result); const token = credential.accessToken; const user = result.user; }).catch((error) => { const errorCode = error.code; const errorMessage = error.message; const email = error.customData.email; const credential = GoogleAuthProvider.credentialFromError(error); }); signInWithRedirect(auth, provider); */
解决方案
1. 修复POST 400错误
POST 400属于客户端请求错误,结合代码排查出两个核心问题:
- 重复初始化Auth实例:
firebaseConfig.js中已初始化并导出auth,但Login函数内又重复调用getAuth(),导致实例冲突。直接使用已导出的auth即可。 - Firebase配置域名不匹配:检查
firebaseConfig中的authDomain是否与当前项目运行域名完全一致,域名不匹配是触发400错误的常见原因。
修改后firebaseConfig.js中的Login函数:
// 直接使用已导出的auth实例,无需重复初始化 export default function Login({email, contraseña}) { signInWithEmailAndPassword(auth, email, contraseña) .then((userCredential) => { // 后续逻辑 }) .catch((error) => { // 错误处理 }); }
2. 登录成功重定向到首页
如果是Web项目(使用react-router-dom),通过useNavigate钩子实现重定向:
- 在
LoginForm中导入useNavigate:
import { Link, useNavigate } from "react-router-dom";
- 组件内初始化导航函数并修改提交逻辑:
export default function LoginForm () { const navigate = useNavigate(); const handleLogin = async (values) => { try { await Login(values); navigate('/'); // 跳转到首页路由 } catch (error) { // 捕获错误并处理 } } return( <Formik initialValues={{ email: '', contraseña: '' }} validationSchema={SignupSchema} onSubmit={handleLogin} > {/* 原有组件内容 */} </Formik> ) }
如果是React Native项目,需替换react-router-dom为@react-navigation/native,使用navigation.navigate('Home')实现跳转。
3. 登录失败的场景区分处理
利用Firebase Auth返回的错误码,区分用户不存在和其他错误场景:
修改firebaseConfig.js中的Login函数,返回Promise并添加错误判断:
export default function Login({email, contraseña}) { return new Promise((resolve, reject) => { signInWithEmailAndPassword(auth, email, contraseña) .then((userCredential) => { resolve(userCredential.user); }) .catch((error) => { const errorCode = error.code; if (errorCode === 'auth/user-not-found') { console.warn('用户不存在,请先注册'); reject(new Error('用户不存在')); } else { console.error('登录失败:', error.message); reject(error); } }); }); }
在LoginForm的handleLogin中可以捕获错误,进一步展示UI提示给用户。
内容的提问来源于stack exchange,提问作者Lucas
相关产品推荐
相关产品推荐

