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

Next.js 15中如何通过useActionState给formAction传额外参数?

问题

在Next.js 15项目的客户端组件联系表单中,已集成Google reCAPTCHA v3。表单提交时先获取验证码token,再调用服务器动作sendEmail,并使用useActionState优化前端体验。但调用formAction(formData, captchaToken)时出现TypeScript错误:"Expected 0 arguments, but got 2",移除captchaToken参数则报错消失。需解决如何将captchaToken与formData一起传递给formAction,让sendEmail接收该参数。

组件代码

const initialState = {
    status: 'success',
    messages: [],
}
const Contact = () => {
  const [state, formAction, isPending] = useActionState(sendEmail, initialState)

  const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault()

    const captchaToken = await getCaptchaToken()

    const formData = new FormData(event.currentTarget)
    formAction(formData, captchaToken)
  }

  return (
    <div>
      <h2>
        Contact
      </h2>
      <form onSubmit={handleSubmit}>
        <label>
          Name
          <input
            required
            type='text'
            name='fname'
            placeholder='enter your first name'
          />
        </label>

        <label>
          Email
          <input
            required
            type='email'
            name='email'
            placeholder='enter your email'
          />
        </label>

        <button>
          {isPending ? 'Pending' : 'Submit'}
        </button>
        {state.messages.length > 0 &&
          state.messages.map((message, index) => {
            return (
              <p
                key={index}
              >
                {message}
              </p>
            )
          })}
      </form>
    </div>
  )
}

服务器动作代码

export async function sendEmail(
  prevState: { messages: string[] },
  formData: FormData,
  captchaToken: string
) {
  // Do some logic with the token and the formData
  return {
    status: 'success',
    messages: ['Thank you for contacting us!']
  }
}
解决方案

useActionState返回的formAction函数仅支持接收0个或1个参数,额外参数会触发TS错误且无法传递到服务器动作。解决核心是将captchaToken合并到FormData中统一传递:

1. 客户端组件:将captchaToken追加到FormData

修改handleSubmit函数,把获取到的验证码token添加到表单数据对象中,再传递给formAction:

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
  event.preventDefault()

  const captchaToken = await getCaptchaToken()
  const formData = new FormData(event.currentTarget)
  
  // 将captchaToken加入FormData
  formData.append('captchaToken', captchaToken)
  
  // 仅传递formData一个参数
  formAction(formData)
}

2. 服务器动作:从FormData中提取captchaToken

调整sendEmail函数的参数结构,移除独立的captchaToken参数,改为从formData中读取:

export async function sendEmail(
  prevState: { messages: string[] },
  formData: FormData
) {
  // 从FormData中取出captchaToken
  const captchaToken = formData.get('captchaToken') as string
  
  // 后续使用captchaToken和表单数据处理业务逻辑
  // ...
  
  return {
    status: 'success',
    messages: ['感谢您的联系!']
  }
}

3. 可选:类型安全优化

若需要严格的类型检查,可定义表单数据类型并做字段校验:

interface ContactFormData {
  fname: string;
  email: string;
  captchaToken: string;
}

export async function sendEmail(
  prevState: { messages: string[] },
  formData: FormData
) {
  const fname = formData.get('fname') as string;
  const email = formData.get('email') as string;
  const captchaToken = formData.get('captchaToken') as string;
  
  // 校验必填字段
  if (!fname || !email || !captchaToken) {
    return {
      status: 'error',
      messages: ['请填写所有必填字段']
    }
  }
  
  // 业务逻辑处理
  // ...
  
  return {
    status: 'success',
    messages: ['感谢您的联系!']
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 02:42:18