通过 localstorage 持久化模态框状态,使用户登出后页面刷新时“登出成功”提示仍可见,直至手动关闭。
在 Next.js(尤其是 App Router 或启用了服务端渲染的场景)中,组件状态(如 useState)会在页面刷新后重置,因此直接使用 setIsModalOpen(true) 无法跨刷新保留模态框。解决该问题的核心思路是:将模态框的显隐状态持久化到浏览器的 localStorage 中,并在组件挂载时从存储中读取初始值。
以下是完整、健壮的实现方案:
"use client";
import "./signinbutton.css";
import { signIn, signOut, useSession } from "next-auth/react";
import Modal from "./Modal";
import React, { useState, useEffect } from "react";
import { AiOutlineUserAdd } from "react-icons/ai";
import { IoMdLogOut } from "react-icons/io";
const SIGNOUT_MODAL_KEY = "SIGNOUT_MODAL_SHOWN";
const SigninButton = ({ darkMode }) => {
const [isModalOpen, setIsModalOpen] = useState(false);
const { data: session } = useSession();
// ✅ 页面加载时从 localStorage 恢复状态(仅客户端执行)
useEffect(() => {
const saved = localStorage.getItem(SIGNOUT_MODAL_KEY);
if (saved === "true") {
setIsModalOpen(true);
}
}, []);
const logOut = async () => {
try {
await signOut({ redirect: false }); // 阻止默认跳转,避免丢失状态
localStorage.setItem(SIGNOUT_MODAL_KEY, "true");
setIsModalOpen(true);
} catch (err) {
console.error("Sign out failed:", err);
}
};
const closeModal = () => {
setIsModalOpen(false);
localStorage.setItem(SIGNOUT_MODAL_KEY, "false");
};
if (session && session.user) {
return (
✅ Sign-out Successful
You have been logged out securely.
);
}
return (
);
};
export default SigninButton;确保 Modal 不依赖外部状态管理逻辑,仅专注渲染。以下为轻量且安全的实现(已兼容服务端渲染):
"use client"; // 必须标记为客户端组件
import React from "react";
import "./modal.css";
const Modal = ({ show, onClose, children }) => {
if (!show) return null;
// 防止服务端渲染时因 window 未定义报错(虽已加 "use client",但双重保险)
if (typeof window === "undefined") return null;
return (
e.stopPropagation()}>
e.stopPropagation()}>
{children}
);
};
export default Modal;
通过以上改造,模态框即可真正“记住”用户操作,在刷新后继续展示,大幅提升用户体验与交互可信度。