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
相关产品推荐
相关产品推荐

