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

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 的类型定义做了严格校验,核心变化有两点:

  1. 参数签名约束收紧:新版本要求传入的action函数必须符合固定签名——要么仅接收state参数,要么接收state和payload(FormData)两个参数,不允许通过bind提前绑定额外前置参数。
  2. 初始状态类型严格匹配:初始状态的类型必须与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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:42:03