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

Next.js登录后无法自动渲染Profile与Logout按钮问题求助

问题解决:登录后需刷新才显示Profile/Logout按钮

你创建了检查Cookie中token的API,登出时导航栏能自动切换状态,但登录后必须刷新页面才会显示Profile和Logout按钮。

问题原因

当前代码中grabEmail仅在Header组件首次挂载时执行一次(空依赖数组的useEffect)。登录操作完成后,Header组件没有重新触发登录状态检查,因此isLoggedIn状态保持初始的false,直到页面刷新重新挂载组件才会更新。


方案1:利用已导入的Auth Context(推荐)

你已经导入了useAuth,说明项目存在全局认证状态管理。直接使用Context中的登录状态代替本地isLoggedIn,登录成功后Context更新时,Header会自动重新渲染。

修改后的代码示例:

import React, { useState } from 'react';
import { useAuth } from '@/app/authContext';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import axios from 'axios';

export default function Header() {
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
  const [showModal, setShowModal] = useState(false); 
  const { isLoggedIn, logout } = useAuth(); // 从Auth Context获取状态和登出方法
  const router = useRouter();

  const toggleMobileMenu = () => {
    setIsMobileMenuOpen(!isMobileMenuOpen);
  };

  const handleMenuItemClick = () => {
    setIsMobileMenuOpen(false);
  };

  const handleLogout = () => {
    setShowModal(true);
  };

  const confirmLogout = async () => {
    try {
      await axios.get('/api/users/logout');
      logout(); // 调用Auth Context的登出方法更新全局状态
      setIsMobileMenuOpen(false); 
      router.push('/');
      setShowModal(false); 
    } catch (error) {
      console.error("Error logging out:", error);
    }
  };

  const closeModal = () => {
    setShowModal(false); 
  };

  // 其余return部分代码保持不变
  return (
    <header className='bg-white border-b flex justify-between p-4'>
      <div className="flex items-center gap-6">
        <Link href={'/'}>FashionFinder </Link>
        <nav className='hidden md:flex gap-4'>
          <Link href={'/about'}>About</Link>
          <Link href={'/contact'}>Contact Us</Link>
          <Link href={'/albums'}>Albums</Link>
        </nav>
      </div>
      <div className="relative md:hidden">
        <button
          id="menu-toggle"
          className="outline-none focus:outline-none"
          onClick={toggleMobileMenu}
        >
          <svg
            className="w-6 h-6"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth="2"
              d="M4 6h16M4 12h16M4 18h16"
            ></path>
          </svg>
        </button>
        {isMobileMenuOpen && (
          <div className="fixed inset-0 bg-gray-700 bg-opacity-50 overflow-y-auto z-50">
            <div className="fixed top-0 right-0 w-1/2 h-screen bg-gray-800 flex flex-col items-center justify-center overflow-y-auto">
              <button
                className="absolute top-4 left-4 outline-none focus:outline-none"
                onClick={toggleMobileMenu}
              >
                <svg
                  className="w-6 h-6 text-white"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth="2"
                    d="M6 18L18 6M6 6l12 12"
                  />
                </svg>
              </button>
              <nav className="flex flex-col items-center gap-4 text-white">
                <Link href="/about" onClick={handleMenuItemClick}>About</Link>
                <Link href="/contact" onClick={handleMenuItemClick}>Contact</Link>
                <Link href="/albums" onClick={handleMenuItemClick}>Albums</Link>
                {isLoggedIn ? (
                  <>
                    <Link href="/profile" onClick={handleMenuItemClick}>Profile</Link>
                    <button
                      onClick={handleLogout}
                      className="text-white"
                    >
                      Logout
                    </button>
                    
                  </>
                ) : (
                  <>
                    <Link href="/login" onClick={handleMenuItemClick}>Sign In</Link>
                    <Link href="/register" onClick={handleMenuItemClick}>Create Account</Link>
                  </>
                )}
              </nav>
            </div>
          </div>
        )}
      </div>
      {/* Full-screen logout modal */}
      {showModal && (
        <div className="fixed inset-0 flex items-center justify-center z-50 bg-gray-700 bg-opacity-50">
          <div className="bg-white p-10 rounded-md shadow-lg">
            <h2 className="text-lg font-semibold mb-4">Are you sure you want to logout?</h2>
            <div className="flex items-center justify-center">
              <button
                className="bg-black text-white px-4 py-2 rounded-md mr-2 font-semibold"
                onClick={confirmLogout}
              >
                Yes
              </button>
              <button
                className="bg-gray-300 text-gray-800 px-4 py-2 rounded-md font-semibold"
                onClick={closeModal}
              >
                No
              </button>
            </div>
          </div>
        </div>
      )}
      <nav className='hidden md:flex items-center gap-4'>
        {isLoggedIn ? (
          <>
            <Link href={'/profile'}>Profile</Link>
            <button
              onClick={handleLogout}
              className="bg-black text-white px-6 py-3 rounded-lg font-semibold text-lg"
            >
              Logout
            </button>
          </>
        ) : (
          <>
            <Link href={'/login'}>Sign In</Link>
            <Link href={'/register'}>Create Account</Link>
          </>
        )}
      </nav>
    </header>
  );
}

方案2:监听路由变化,重新检查登录状态

如果暂时不想用Auth Context,可以让Header在路由变化时重新调用grabEmail检查登录状态(登录后通常会跳转页面,路由变化会触发检查)。

修改后的关键代码片段:

// ... 其他导入和状态定义

useEffect(() => {
  grabEmail();
}, [router]); // 添加router作为依赖,路由变化时重新执行

const grabEmail = async () => {
  try {
    // 统一路径为绝对路径,和登出接口保持一致
    const response = await axios.get('/api/users/grabUserEmail');
    setIsLoggedIn(true); 
  } catch (error) {
    setIsLoggedIn(false); 
  }
};

// ... 其余代码不变

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:02:09