useFormState调用无匹配重载:原因分析与代码适配方案
问题:useFormState 升级后出现“无匹配重载”错误
作为Web应用开发新手,使用useFormState构建数据库条目编辑表单时遇到问题,此前可用的代码现在提示“无匹配重载”错误。
组件代码
export default function EditDataCatalogEntryForm({ data }: { data: DataCatalogFile }) { const initialState = { message: null, errors: {} }; const updateDataCatalogEntryWithId = updateDataCatalogEntry.bind(null, data.file_id); const [state, dispatch] = useFormState(updateDataCatalogEntryWithId, initialState); /*...other function code...*/ }
updateDataCatalogEntry函数定义
(alias) function updateDataCatalogEntry(id: number, prevState: State, formData: FormData): Promise<{ errors: { source?: string[] | undefined; s3_location?: string[] | undefined; tags?: string[] | undefined; file_name?: string[] | undefined; description?: string[] | undefined; }; message: string; }>
错误信息
No overload matches this call. Overload 1 of 2, '(action: (state: { errors: { source?: string[] | undefined; s3_location?: string[] | undefined; tags?: string[] | undefined; file_name?: string[] | undefined; description?: string[] | undefined; }; message: string; }) => { ...; } | Promise<...>, initialState: { ...; }, permalink?: string | undefined): [state: ...]', gave the following error. Argument of type '(prevState: State, formData: FormData) => Promise<{ errors: { source?: string[] | undefined; s3_location?: string[] | undefined; tags?: string[] | undefined; file_name?: string[] | undefined; description?: string[] | undefined; }; message: string; }>' is not assignable to parameter of type '(state: { errors: { source?: string[] | undefined; s3_location?: string[] | undefined; tags?: string[] | undefined; file_name?: string[] | undefined; description?: string[] | undefined; }; message: string; }) => { ...; } | Promise<...>'. Target signature provides too few arguments. Expected 2 or more, but got 1. Overload 2 of 2, '(action: (state: { errors: { source?: string[] | undefined; s3_location?: string[] | undefined; tags?: string[] | undefined; file_name?: string[] | undefined; description?: string[] | undefined; }; message: string; }, payload: FormData) => { ...; } | Promise<...>, initialState: { ...; }, permalink?: string | undefined): [state: ...]', gave the following error. Argument of type '{ message: null; errors: {}; }' is not assignable to parameter of type '{ errors: { source?: string[] | undefined; s3_location?: string[] | undefined; tags?: string[] | undefined; file_name?: string[] | undefined; description?: string[] | undefined; }; message: string; }'. Types of property 'message' are incompatible. Type 'null' is not assignable to type 'string'.ts(2769) (alias) useFormState<{ errors: { source?: string[] | undefined; s3_location?: string[] | undefined; tags?: string[] | undefined; file_name?: string[] | undefined; description?: string[] | undefined; }; message: string; }>(action: (state: { ...; }) => { ...; } | Promise<...>, initialState: { ...; }, permalink?: string | undefined): [state: ...] (+1 overload)
项目依赖版本
{ "name": "my_app", "version": "1.0.0", "description": "Broken app", "main": "next.config.js", "scripts": { "build": "next build", "dev": "next dev", "start": "next start", "seed": "node -r dotenv/config ./scripts/seed.js", "lint": "next lint" }, "author": "", "license": "ISC", "dependencies": { "@heroicons/react": "^2.1.1", "@nextui-org/react": "^2.2.9", "autoprefixer": "^10.4.17", "dotenv": "^16.4.1", "next": "^14.1.0", "pg": "^8.11.3", "react": "^18.2.0", "react-dom": "^18.2.0", "use-debounce": "^10.0.0", "zod": "^3.22.4" }, "devDependencies": { "@types/node": "^20.11.6", "@types/pg": "^8.10.9", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", "typescript": "^5.3.3" } }
此前相同用法可正常运行,确认是useFormState更新导致的问题,想知道函数变更原因及代码适配方案。
解决方案
一、useFormState 变更原因
Next.js 14+ 对 useFormState 的类型定义做了严格校验,核心变化有两点:
- 参数签名约束收紧:新版本要求传入的action函数必须符合固定签名——要么仅接收
state参数,要么接收state和payload(FormData)两个参数,不允许通过bind提前绑定额外前置参数。 - 初始状态类型严格匹配:初始状态的类型必须与action函数返回的状态类型完全一致,不再允许宽松的类型兼容(比如
message: null与message: string的差异)。
二、代码修改方案
1. 调整action函数的参数传递方式
放弃用bind绑定id,改用闭包传递参数,确保action函数符合新版本的签名要求:
export default function EditDataCatalogEntryForm({ data }: { data: DataCatalogFile }) { // 1. 修正初始状态,匹配返回值的类型要求 const initialState = { message: "", errors: {} as { source?: string[]; s3_location?: string[]; tags?: string[]; file_name?: string[]; description?: string[]; } }; // 2. 用闭包封装原函数,传递id参数 const updateAction = async (prevState: typeof initialState, formData: FormData) => { return updateDataCatalogEntry(data.file_id, prevState, formData); }; const [state, dispatch] = useFormState(updateAction, initialState); /*...other function code...*/ }
2. 修正初始状态的类型不兼容问题
将原初始状态的message: null改为空字符串"",同时为errors指定明确的类型,确保与action返回的错误结构一致,消除类型匹配错误。
3. (可选)统一State类型定义
如果项目中已有State类型声明,确保其与action返回的状态结构完全一致:
type State = { message: string; errors: { source?: string[]; s3_location?: string[]; tags?: string[]; file_name?: string[]; description?: string[]; }; };
完成以上修改后,代码即可满足新版本useFormState的类型约束,解决“无匹配重载”的错误。
内容的提问来源于stack exchange,提问作者JaW
相关产品推荐
相关产品推荐

