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

Next.js 13 App Router中react-hook-form的redirect失效问题求助

解决方案:Next.js 13 App Router + React Hook Form 登录跳转注册页

在Next.js 13 App Router的客户端组件中,redirect函数通过抛出特殊错误实现跳转,一旦被try/catch捕获就会失效,且直接在非组件顶层调用容易引发未处理运行时错误。推荐使用客户端导航API useRouter().push() 替代,以下是完整实现方案:

1. 核心逻辑:用useRouter替代redirect

在表单处理的客户端组件中,使用Next.js提供的useRouter进行导航,它不会抛出错误,可安全用于条件判断或错误处理流程中。

2. 完整代码示例

父组件(LoginPage):管理表单逻辑与跳转

'use client'

import { FormProvider, useForm } from 'react-hook-form'
import { useRouter } from 'next/navigation'
import LoginFormFields from './LoginFormFields'
import SubmitButton from './SubmitButton'

export default function LoginPage() {
  const router = useRouter()
  const formMethods = useForm({
    defaultValues: { email: '', password: '' }
  })
  const { handleSubmit } = formMethods

  // 表单提交处理函数
  const onSubmit = async (formData) => {
    try {
      // 调用后端接口检查邮箱是否存在
      const checkRes = await fetch('/api/check-user-email', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: formData.email })
      })
      const checkResult = await checkRes.json()

      if (!checkResult.userExists) {
        // 邮箱不存在,跳转到注册页
        router.push('/register')
        return
      }

      // 邮箱存在,执行登录逻辑
      const loginRes = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(formData)
      })

      if (loginRes.ok) {
        // 登录成功跳转到首页
        router.push('/')
      } else {
        console.error('登录失败:', await loginRes.text())
      }
    } catch (err) {
      console.error('请求出错:', err)
    }
  }

  return (
    <FormProvider {...formMethods}>
      <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
        <LoginFormFields />
        <SubmitButton />
      </form>
    </FormProvider>
  )
}

表单字段组件(LoginFormFields):渲染输入框

'use client'

import { useFormContext } from 'react-hook-form'

export default function LoginFormFields() {
  const { register } = useFormContext()

  return (
    <>
      <div>
        <label htmlFor="email">邮箱</label>
        <input
          id="email"
          type="email"
          {...register('email', { required: '请输入邮箱' })}
          className="w-full mt-1 p-2 border"
        />
      </div>
      <div>
        <label htmlFor="password">密码</label>
        <input
          id="password"
          type="password"
          {...register('password', { required: '请输入密码' })}
          className="w-full mt-1 p-2 border"
        />
      </div>
    </>
  )
}

提交按钮组件(SubmitButton):独立渲染提交按钮

'use client'

export default function SubmitButton() {
  return (
    <button
      type="submit"
      className="w-full p-2 bg-blue-500 text-white rounded"
    >
      登录
    </button>
  )
}

关键说明

  • 为什么不用redirect:redirect依赖抛出错误实现跳转,若被try/catch捕获则跳转失效;而useRouter().push()是客户端导航的常规API,无错误抛出问题,适合在条件判断中直接调用。
  • FormProvider传递逻辑:通过FormProvider将表单方法传递给子组件,确保输入框和提交按钮共享同一个表单状态,符合React Hook Form的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:44:58