大数据

Nextjs 问题记录

1、server端使用redirect函数跳转

createWorkflow.ts

"use server"

import prisma from "@/lib/prisma";
import { createWorkflowSchema, createWorkflowSchemaType } from "@/schema/workflow";
import { WorkflowStatus } from "@/types/workflow";
import { redirect } from "next/navigation";

export async function CreateWorkflow(form: createWorkflowSchemaType) {
    const {success, data} = createWorkflowSchema.safeParse(form)
    if (!success) {
        throw new Error("invalid form data")
    }
    
    // const {userId} = auth()
    // if (!userId) {
        // throw new Error("unauthenticated")
    // }

    const userId = "test"

    const result = await prisma.workflow.create({
        data: {
            userId,
            status: WorkflowStatus.DRAFT,
            definition: "TODO",
            ...data
        }
    })

    if (!result) {
        throw new Error("failed to create workflow")
    }

    redirect(`/workflow/editor/${result.id}`)
}

client端使用 useMutation捕获server端结果

...
    const { mutate, isPending } = useMutation({
        mutationFn: CreateWorkflow,
        onSuccess: () => {
            // 正常情况下不会执行,因为服务端 redirect 会触发 onError
        },
        onError: (error) => {
            if (error instanceof Error && error.message.includes("NEXT_REDIRECT")) {
                toast.success("Workflow created", { id: "create-workflow" })
            } else {
                // 真正的错误
                console.error("Create workflow error:", error);
                toast.error("Failed to create workflow", { id: "create-workflow" });
            }
        }
    })
...

关键点说明

  1. redirect 的工作原理
    • Next.js 的 redirect 实际上会抛出一个特殊的错误(包含 NEXT_REDIRECT
    • 这个错误会被 React Query 的 onError 捕获
  2. 错误类型判断
    • 通过检查 error.message.includes("NEXT_REDIRECT") 区分是正常跳转还是真实错误
    • 如果是跳转,显示成功提示并关闭对话框
  3. 用户体验优化
    • 在 onError 中先显示成功 toast,再关闭对话框
    • 真实错误会显示错误提示并记录日志