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

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;

方案说明

  1. 合规性:通过路由处理器修改Cookie,符合Next.js App Router的规则
  2. 安全性:设置短过期时间和sameSite: 'lax'属性,降低Cookie滥用风险
  3. 复用性:路由处理器支持传递任意消息和类型,可用于其他重定向场景
  4. 用户体验:Toast仅显示一次,不会在页面刷新后重复出现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 22:13:18