如何在Next.js中通过experimental_useFormState向服务器动作传参?
如何在Next.js的experimental_useFormState中向服务器动作传递参数
你遇到的TypeScript错误核心原因是:useFormState要求服务器动作的第一个参数是当前的表单状态对象,第二个才是提交的FormData。之前的写法把FormData作为第一个参数传入,导致类型不匹配。
正确实现步骤
1. 修改服务器动作的函数签名
给动作函数添加状态参数,并明确状态类型:
// app/actions.ts import { revalidatePath } from 'next/cache'; // 定义表单状态的类型 type FormState = { message?: string; error?: string; }; // 第一个参数是当前状态,第二个是提交的FormData export default async function submit(state: FormState, formData: FormData) { try { // 从FormData中获取表单字段(注意input必须有name属性) const email = formData.get('email') as string; console.log('提交的邮箱:', email); // 模拟异步操作 await new Promise<void>((res) => setTimeout(res, 2000)); revalidatePath('/'); // 返回更新后的状态 return { message: `感谢您的提交,${email}!` }; } catch (e) { console.error(e); return { error: '提交失败,请稍后重试' }; } }
2. 调整组件中的useFormState调用
确保初始状态和状态类型匹配,同时给表单input添加name属性:
// someForm.tsx import { experimental_useFormState as useFormState } from 'react-dom'; import submit from '@/app/actions'; // 初始状态要和动作函数返回的结构一致 const initialState = { message: '', error: '', }; const [formStatus, formAction] = useFormState(submit, initialState); export default function SomeForm() { return ( <form action={formAction}> {/* 必须添加name属性,否则FormData无法获取值 */} <input name="email" aria-label='email address' type='email' placeholder='Enter your email' defaultValue='foo' /> {/* 显示状态反馈 */} {formStatus.message && <p>{formStatus.message}</p>} {formStatus.error && <p style={{ color: 'red' }}>{formStatus.error}</p>} <button type='submit'>Contact Us</button> </form> ); }
关键注意事项
- input的name属性:没有name的表单字段不会被包含在FormData中,这是表单提交的基础规则
- 状态类型一致性:初始状态、动作函数的state参数、返回值的结构必须一致,避免TypeScript类型错误
- useFormState的函数签名:动作函数的第一个参数始终是当前状态,第二个参数是提交的payload(FormData或其他自定义数据)
内容的提问来源于stack exchange,提问作者Fer Toasted
相关产品推荐
相关产品推荐

