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

使用React+Formik+Yup实现Firebase登录时出现POST 400错误

问题及解决方案

问题描述

  1. 登录功能验证测试后控制台出现POST 400错误,密码仅设置了最小/最大字符数校验规则,结果不符合预期。
  2. 登录成功后需要实现重定向到首页的逻辑。
  3. 登录失败时,需区分场景:用户不存在时抛出警告,其他错误场景抛出错误提示。

相关代码

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钩子实现重定向:

  1. 在LoginForm中导入useNavigate:
import { Link, useNavigate } from "react-router-dom";
  1. 组件内初始化导航函数并修改提交逻辑:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:50:47