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

React Context封装的login函数调用报错,疑为语法问题求助

问题排查:React Context封装Firebase登录函数报错

问题现象

  • 调用React Context提供的login函数时,抛出错误:Firebase: Error (auth/invalid-value-(email),-starting-an-object-on-a-scalar-field)
  • 直接调用Firebase原生signInWithEmailAndPassword函数则正常工作,且两种调用的参数完全一致

错误原因

核心问题是参数不匹配:
Context中的login函数内部已经封装了全局auth实例,仅需传入email和password两个参数;但调用时额外传入了auth对象,导致Firebase把auth对象当作email参数处理——而email要求是字符串(标量值),传入对象直接触发了类型错误。

修复方案

1. 修正Login.tsx中的函数调用

移除多余的auth参数,只传入email和password:

// Login.tsx 修正后代码
import { useAuth } from '../../config/AuthContext';
import { useRouter } from 'next/router';

export function AuthenticationForm(props: PaperProps) {
  const { login } = useAuth();
  const router = useRouter();

  const handleLogin = async (data: LoginType) => {
    try {
      await login(data.email, data.password); // 移除多余的auth参数
      router.push("/Dashboard");
    } catch (error: any) {
      console.log(error.message);
    }
  };

  return (
    // ... 表单代码
    <form onSubmit={form.onSubmit(handleLogin)}>
      {/* ... 表单元素 */}
    </form>
  );
}

2. 补全AuthContext中的缺失函数

原代码中AuthContext.Provider的value包含logout,但未定义该函数,需要补上:

// AuthContext.tsx 中添加logout函数
const logout = () => {
  return signOut(auth);
};

3. 优化Context类型定义(可选)

为避免后续类型不匹配问题,给Context添加明确的类型约束,替换any类型:

// AuthContext.tsx 完整修正代码
import React, { createContext, useContext, useEffect, useState } from "react";
import {
  onAuthStateChanged,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut,
} from "firebase/auth";
import { auth } from "./firebase";

interface UserType {
  email: string | null;
  uid: string | null;
}

interface AuthContextType {
  user: UserType;
  register: (email: string, password: string) => Promise<any>;
  login: (email: string, password: string) => Promise<any>;
  logout: () => Promise<void>;
}

const AuthContext = createContext<AuthContextType>({
  user: { email: null, uid: null },
  register: async () => {},
  login: async () => {},
  logout: async () => {},
});

export const useAuth = () => useContext(AuthContext);

export const AuthContextProvider = ({ children }: { children: React.ReactNode }) => {
  const [user, setUser] = useState<UserType>({ email: null, uid: null });
  const [loading, setLoading] = useState<boolean>(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (user) => {
      if (user) {
        setUser({ email: user.email, uid: user.uid });
      } else {
        setUser({ email: null, uid: null });
      }
      setLoading(false); // 将setLoading移到回调内,确保监听完成后再渲染子组件
    });

    return () => unsubscribe();
  }, []);

  const register = (email: string, password: string) => {
    return createUserWithEmailAndPassword(auth, email, password);
  };

  const login = (email: string, password: string) => {
    return signInWithEmailAndPassword(auth, email, password);
  };

  const logout = () => {
    return signOut(auth);
  };

  return (
    <AuthContext.Provider value={{ user, register, login, logout }}>
      {loading ? null : children}
    </AuthContext.Provider>
  );
};

4. 修正_app.tsx的语法错误

原代码中return语句前多了多余的分号,修正后:

// _app.tsx 修正后代码
import { AuthContextProvider } from "../config/AuthContext";
import Head from "next/head";
import { NotificationsProvider } from "你的通知库路径";

export default function App(props: AppProps & { colorScheme: ColorScheme }) {
  const { Component, pageProps } = props;

  return (
    <AuthContextProvider>
      <Head>
        <title>Awesome App</title>
      </Head>
      <NotificationsProvider>
        <Component {...pageProps} />
      </NotificationsProvider>
    </AuthContextProvider>
  );
}

App.getInitialProps = async (appContext: AppContext) => {
  const appProps = await NextApp.getInitialProps(appContext);
  return { ...appProps };
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:30:52