Next.js App Router中重定向后如何显示Toast提示?
解决Next.js App Router中服务器端重定向后显示Toast的问题
核心问题分析
你遇到的错误 Cookies can only be modified in a Server Action or Route Handler 是因为Next.js App Router的服务器组件不允许直接修改Cookie,必须通过**路由处理器(Route Handler)或服务器动作(Server Action)**来完成。下面是完整的实现方案:
步骤1:修改登录页的重定向逻辑
将原服务器组件中的直接重定向改为跳转至专门处理Cookie设置的路由处理器:
// /login/page.tsx import styles from "@/app/styles/auth.module.css"; import LoginComponent from "@/app/components/Auth/LoginComponent"; import { redirect } from "next/navigation"; import { getUserSession } from "@/lib/session/session.server"; async function LoginPage() { const session = await getUserSession(); if (session) { // 对消息进行URL编码,避免特殊字符问题 const encodedMessage = encodeURIComponent("You are already logged in"); return redirect(`/api/redirect-with-toast?message=${encodedMessage}&type=error`); } return ( <div className={styles.container}> <div className={styles.content}> <div className={styles.header}> <span>Login</span> </div> <div className={styles.main}> <LoginComponent /> </div> </div> </div> ); } export default LoginPage;
步骤2:创建路由处理器设置Cookie并完成重定向
新建路由处理器文件,负责设置临时Cookie并跳转至目标页面:
// /app/api/redirect-with-toast/route.ts import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const encodedMessage = searchParams.get('message'); const type = searchParams.get('type'); if (encodedMessage && type) { const message = decodeURIComponent(encodedMessage); const cookieStore = cookies(); // 设置临时Cookie,允许客户端读取并设置短过期时间 cookieStore.set('_toast', message, { httpOnly: false, maxAge: 60, // 1分钟后自动过期 path: '/', sameSite: 'lax' }); cookieStore.set('_toast_type', type, { httpOnly: false, maxAge: 60, path: '/', sameSite: 'lax' }); } // 跳转至首页 redirect('/'); }
步骤3:更新客户端组件读取Cookie并显示Toast
修改ToastServerMessage组件,读取Cookie后显示Toast并立即删除Cookie:
// /components/ToastServerMessage.tsx "use client"; import { useEffect } from "react"; import cookies from "js-cookie"; import toast from "react-hot-toast"; function ToastServerMessage() { useEffect(() => { const toastMessage = cookies.get("_toast"); const toastType = cookies.get("_toast_type"); if (toastMessage && toastType) { // 根据类型显示对应Toast switch (toastType) { case "error": toast.error(toastMessage); break; case "success": toast.success(toastMessage); break; default: toast(toastMessage); } // 显示后立即删除Cookie,避免重复展示 cookies.remove("_toast"); cookies.remove("_toast_type"); } }, []); return <></>; } export default ToastServerMessage;
方案说明
- 合规性:通过路由处理器修改Cookie,符合Next.js App Router的规则
- 安全性:设置短过期时间和
sameSite: 'lax'属性,降低Cookie滥用风险 - 复用性:路由处理器支持传递任意消息和类型,可用于其他重定向场景
- 用户体验:Toast仅显示一次,不会在页面刷新后重复出现
内容的提问来源于stack exchange,提问作者Galbert
相关产品推荐
相关产品推荐

