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

Next.js中Firebase邮箱密码登录报错问题排查

问题根源及修复方案

核心错误:window is not defined

报错明确指向Firebase配置文件在服务端渲染时访问了window对象——Next.js的App Router默认会对页面进行服务端渲染(SSR),而服务端环境不存在window。你的Firebase初始化代码里大概率直接在服务端执行了依赖浏览器环境的逻辑(比如Analytics初始化)。

修复Firebase配置文件

修改@/app/firebase/config.js,确保仅在客户端环境初始化Firebase,并且避免在服务端加载Analytics:

// app/firebase/config.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  // 你的Firebase配置信息
};

// 仅在客户端环境初始化Firebase相关服务
let app;
let auth;

if (typeof window !== "undefined") {
  app = initializeApp(firebaseConfig);
  auth = getAuth(app);

  // 按需初始化Analytics,仅在支持的环境加载
  import("firebase/analytics").then(({ getAnalytics, isSupported }) => {
    isSupported().then((supported) => {
      if (supported) getAnalytics(app);
    });
  });
}

export { auth };

登录逻辑优化与跳转修复

除了Firebase初始化问题,同步优化登录逻辑确保跳转正常:

  • 利用react-firebase-hooks返回的状态直接监听登录结果,替代try/catch更符合hooks使用习惯
  • 确保登录成功后再执行跳转逻辑

修改后的登录页面代码:

'use client'

import { useState } from 'react';
import { useSignInWithEmailAndPassword } from 'react-firebase-hooks/auth'
import { auth } from '@/app/firebase/config'
import { useRouter } from 'next/navigation';

const SignIn = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [signInWithEmailAndPassword, user, loading, error] = useSignInWithEmailAndPassword(auth);
  const router = useRouter()

  const handleSignIn = async () => {
    await signInWithEmailAndPassword(email, password);
  };

  // 登录成功后自动跳转首页
  if (user) {
    sessionStorage.setItem('user', JSON.stringify(user));
    router.push('/');
  }

  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-900">
      <div className="bg-gray-800 p-10 rounded-lg shadow-xl w-96">
        <h1 className="text-white text-2xl mb-5">Sign In</h1>
        {error && <p className="text-red-400 mb-4">{error.message}</p>}
        <input 
          type="email" 
          placeholder="Email" 
          value={email} 
          onChange={(e) => setEmail(e.target.value)} 
          className="w-full p-3 mb-4 bg-gray-700 rounded outline-none text-white placeholder-gray-500"
          disabled={loading}
        />
        <input 
          type="password" 
          placeholder="Password" 
          value={password} 
          onChange={(e) => setPassword(e.target.value)} 
          className="w-full p-3 mb-4 bg-gray-700 rounded outline-none text-white placeholder-gray-500"
          disabled={loading}
        />
        <button 
          onClick={handleSignIn}
          className="w-full p-3 bg-indigo-600 rounded text-white hover:bg-indigo-500 disabled:bg-indigo-800"
          disabled={loading}
        >
          {loading ? 'Signing In...' : 'Sign In'}
        </button>
      </div>
    </div>
  );
};

export default SignIn;

额外注意事项

  • 所有依赖浏览器API(如window、sessionStorage)的代码必须放在标记了'use client'的组件内
  • 避免在服务端执行任何仅浏览器支持的Firebase服务初始化逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 13:54:54