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

Next.js 14 App Router:SSR页面表单提交后重复触发verifySignupToken问题

问题分析与解决方案

核心原因排查

你的问题本质是表单提交后触发了当前SSR页面的重复请求,导致verifySignupToken被二次调用,常见诱因有以下几种:

  1. 未捕获服务端Action错误:如果signupAction执行时抛出未处理的异常,会导致客户端Action执行失败,表单默认提交行为被触发,浏览器刷新当前页面,进而重新执行SSR页面的验证逻辑。
  2. 服务端Action触发页面重验证:若signupAction中调用了revalidatePath('/signup'),会强制重新渲染当前页面的服务器组件,直接触发verifySignupToken。
  3. 路由跳转逻辑冲突:如果signupAction内部已经通过redirect完成导航,同时客户端又调用router.push,可能导致导航异常,页面意外重新加载。

针对性解决方案

1. 捕获服务端Action所有错误

在客户端Action中用try-catch包裹signupAction调用,避免未捕获错误触发页面刷新:

const signUpClientAction = async (formData: FormData) => {
  const password = formData.get('password')
  const pnr = formData.get('pnr')

  const result = safeParse(SignUpSchema, { password, pnr })

  if (!result.success) {
    toast.error(result.issues[0].message)
    return
  }

  const validatedData = result.output

  try {
    const response = await signupAction(
      email,
      validatedData.password,
      token,
      validatedData.pnr,
      customerId
    )

    if (response.success) {
      toast.success(response.message)
      router.push('/')
    } else if (response.statusCode === 401) {
      toast.error(response.message)
      router.push('/login')
    } else {
      toast.error(response.message)
    }
  } catch (error) {
    console.error('注册请求失败:', error)
    toast.error('注册失败,请稍后重试')
  }
}

2. 移除不必要的页面重验证

检查signupAction代码,若存在revalidatePath('/signup')这类调用,直接删除,避免强制重新渲染当前页面。

3. 统一路由跳转逻辑

如果signupAction内部已经通过redirect完成导航,移除客户端的router.push调用,避免冲突:

// 服务端Action示例(signupAction)
export async function signupAction(...) {
  // 注册逻辑处理
  if (success) {
    redirect('/')
  }
  // 错误处理逻辑
}

// 客户端Action中移除router.push
const signUpClientAction = async (formData: FormData) => {
  // ...参数验证逻辑
  try {
    await signupAction(...)
    // 无需手动调用router.push,服务端Action会自动处理跳转
  } catch (error) {
    toast.error('注册失败,请稍后重试')
  }
}

4. 手动阻止表单默认行为

虽然Next.js会自动阻止表单默认提交,但可以添加防御性代码确保:

<form 
  className="space-y-6" 
  onSubmit={(e) => {
    e.preventDefault()
    signUpClientAction(new FormData(e.target as HTMLFormElement))
  }}
>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:48:10