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

React Firebase登录跳转异常:需刷新进首页的修复咨询

问题描述

在React项目中集成Firebase身份验证,调用signInWithEmailAndPassword完成登录后执行navigate('/'),却被重定向到/landing页面,必须刷新才能进入首页。相关代码如下:

登录组件(Login Component)

import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "./firebase.js";

export default LoginComponent = () => {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const navigate = useNavigate();

    const handleSubmit = (e) => {
        e.preventDefault();
        signInWithEmailAndPassword(auth, email, password).then(() => {
            navigate('/')
        }).catch((error) => {
        });
    };

    // 组件渲染代码省略
};

身份验证提供者(AuthProvider)

import { onAuthStateChanged } from "firebase/auth";
import { createContext, useEffect, useState } from "react";
import PropTypes from "prop-types";
import { auth } from "./firebase.js";

export const AuthContext = createContext(null);

const AuthProvider = ({ children }) => {
    const [user, setUser] = useState(null);
    const [loading, setLoading] = useState(true);
    const [accessToken, setAccessToken] = useState(null);

    useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, async (currentUser) => {
            if (currentUser) {
                setAccessToken(await currentUser.getIdToken(true));
            }
            setUser(currentUser);
            setLoading(false);
        });

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

    const authValue = {
        user,
        loading,
        accessToken,
    };

    return <AuthContext.Provider value={authValue}>{children}</AuthContext.Provider>;
};

AuthProvider.propTypes = {
    children: PropTypes.node.isRequired,
};

export default AuthProvider;

路由页面代码

import { useContext } from 'react'
import { AuthContext } from "./components/Auth/AuthProvider.js";
import UserProfile from "./components/UserProfile"
import { Navigate } from 'react-router-dom';

const App = () => {
    const { user, loading } = useContext(AuthContext);

    function LandingPageRedirect({ children }) {
        if (loading) {
            return <div>Loading...</div>; 
        }
        if (user) {
            return <>{children}</>
        } else {
            return (
                <Navigate
                to="/landing"
                state={{
                    from: location.pathname,
                }}
                replace
                />
            )
        }
    }

    return (
        <div>
            <BrowserRouter>
                <Routes>
                    <Route path='/' element={
                            <LandingPageRedirect>
                                <Home />
                            </LandingPageRedirect>
                        } 
                    />
                    {/* 其他路由省略 */}
                </Routes>
            </BrowserRouter>
        </div>
    );
};
解决方案

1. 修复登录组件:监听用户状态变化再跳转

登录成功后直接调用navigate时,AuthContext的user状态尚未更新,路由守卫会读取旧的null值导致重定向。改为监听user状态,确认用户已登录后再跳转:

import React, { useState, useContext, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "./firebase.js";
import { AuthContext } from "./AuthProvider"; // 根据实际路径调整

// 修复导出语法
export default function LoginComponent() {
    const [email, setEmail] = useState("");
    const [password, setPassword] = useState("");
    const navigate = useNavigate();
    const { user } = useContext(AuthContext);

    // 监听user状态,存在时跳转首页
    useEffect(() => {
        if (user) {
            navigate('/');
        }
    }, [user, navigate]);

    const handleSubmit = (e) => {
        e.preventDefault();
        signInWithEmailAndPassword(auth, email, password)
            .catch((error) => {
                // 添加错误处理,比如提示用户
                console.error('登录失败:', error.message);
            });
    };

    // 组件渲染代码...
}

2. 调整AuthProvider状态更新顺序(可选)

将setUser提前到getIdToken之前,确保用户状态优先更新,路由守卫能更快检测到已登录状态:

useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, async (currentUser) => {
        // 先更新user状态
        setUser(currentUser);
        if (currentUser) {
            setAccessToken(await currentUser.getIdToken(true));
        } else {
            setAccessToken(null); // 登出时清除token
        }
        setLoading(false);
    });

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

3. 修复路由守卫中的location未定义问题

LandingPageRedirect组件中location变量未声明,需导入并使用useLocation钩子:

import { Navigate, useLocation } from 'react-router-dom';
import { useContext } from 'react';
import { AuthContext } from "./components/Auth/AuthProvider.js";

function LandingPageRedirect({ children }) {
    const location = useLocation(); // 添加这行
    const { user, loading } = useContext(AuthContext);

    if (loading) {
        return <div>Loading...</div>; 
    }
    if (user) {
        return <>{children}</>;
    } else {
        return (
            <Navigate
                to="/landing"
                state={{
                    from: location.pathname,
                }}
                replace
            />
        );
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 20:37:04