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

Next.js 14 Server Action在RSC中使用触发ESLint错误求助

Server Component中使用Server Action的ESLint错误解决

问题描述

在Next.js 14的Server Component中编写带Server Action的表单时,触发两个ESLint错误,代码示例如下:

// /app/search/page.tsx
export default function Search() {
  async function updateResults(formData: FormData) {
    "use server";
    await new Promise((resolve) => setTimeout(resolve, 150));
    console.log("input value => ", formData.get("me"));
    revalidatePath("/search");
  }
 return (
    <>
      <form action={updateResults}>  {/* eslint errors here */}
        <input name="me" type="text" />
        <button type="submit">Update</button>
      </form>
    </>
  )
}

在<form action={updateResults}>处触发的错误:

  • JSX props should not use functions eslint(react/jsx-no-bind)
  • Promise-returning function provided to attribute where a void return was expected. eslint(@typescript-eslint/no-misused-promises)

当前环境:Next.js 14、ESLint 8.36,相关配置如下:

package.json依赖片段

"dependencies": {
    "@next/third-parties": "^14.0.4",
    "i18next": "^23.0.0",
    "js-cookie": "^3.0.5",
    "lodash": "^4.17.21",
    "next": "^14.0.3",
    "next-i18next": "^15.0.0",
    "next-intl": "^3.2.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-i18next": "^14.0.0",
    "server-only": "^0.0.1",
    "sharp": "^0.33.0"
  },
  "devDependencies": {
    "@ianvs/prettier-plugin-sort-imports": "^4.0.2",
    "@storybook/addon-designs": "^7.0.1",
    "@storybook/addon-essentials": "^7.1.0",
    "@storybook/nextjs": "^7.1.0",
    "@storybook/react": "^7.1.0",
    "@testing-library/dom": "^9.0.1",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/jest-axe": "^3.5.5",
    "@types/js-cookie": "^3.0.6",
    "@types/node": "^20.8.2",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@typescript-eslint/eslint-plugin": "^5.55.0",
    "@typescript-eslint/parser": "^5.55.0",
    "eslint": "^8.36.0",
    "eslint-config-mycustomconfig": "^12.1.0",
    "eslint-config-next": "^13.2.4",
    "eslint-config-prettier": "^8.7.0",
    "eslint-plugin-jest": "^27.2.1",
    "eslint-plugin-jest-dom": "^5.0.1",
    "eslint-plugin-storybook": "^0.6.12",
    "eslint-plugin-testing-library": "^5.11.0",
    "i18next-browser-languagedetector": "^7.0.2",
    "i18next-http-backend": "^2.2.1",
    "jest": "^29.5.0",
    "jest-axe": "^7.0.0",
    "jest-cli": "^29.5.0",
    "jest-environment-jsdom": "^29.5.0",
    "postcss": "^8.4.31",
    "postcss-loader": "^7.1.0",
    "postcss-preset-env": "^8.0.1",
    "prettier": "^3.2.5",
    "sass": "^1.59.3",
    "sass-loader": "^13.2.0",
    "storybook": "^7.1.0",
    "storybook-react-i18next": "^2.0.6",
    "style-loader": "^3.3.2",
    "typescript": "^5.0.0"
  }

eslintrc.js配置

module.exports = {
  root: true,
  extends: [
    "plugin:storybook/recommended",
    // Disable ESLint code formatting rules which conflict with Prettier
    "prettier",
    // `next` should be extended last according to their docs
    // https://nextjs.org/docs/basic-features/eslint
    "next/core-web-vitals",
  ],
  rules: {
    // Next.js <Image> component is useful for optimizing images, but also requires additional
    // dependencies to work in standalone mode. It may be overkill for most projects at
    // Which aren't image heavy.
    "@next/next/no-img-element": "off",
  },
  // Additional lint rules. These get layered onto the top-level rules.
  overrides: [
    // Lint config specific to Test files
    {
      files: ["tests/**"],
      plugins: ["jest"],
      extends: [
        "plugin:jest/recommended",
        "plugin:jest-dom/recommended",
        "plugin:testing-library/react",
      ],
    },
    // Lint config specific to TypeScript files
    {
      files: "**/*.+(ts|tsx)",
      parserOptions: {
        // These paths need defined to support rules that require type information
        tsconfigRootDir: __dirname,
        project: ["./tsconfig.json"],
      },
      extends: [
        "plugin:@typescript-eslint/recommended",
        // Disable vanilla ESLint rules that conflict with those in @typescript-eslint
        "plugin:@typescript-eslint/eslint-recommended",
        // Rules that specifically require type information
        "plugin:@typescript-eslint/recommended-requiring-type-checking",
      ],
      plugins: ["@typescript-eslint"],
      rules: {
        // Prevent dead code accumulation
        "@typescript-eslint/no-unused-vars": "error",
        // The usage of `any` defeats the purpose of typescript. Consider using `unknown` type instead instead.
        "@typescript-eslint/no-explicit-any": "error",
      },
    },
  ],
  settings: {
    // Support projects where Next.js isn't installed in the root directory (such as a monorepo)
    next: {
      rootDir: __dirname,
    },
  },
};

原因分析

这两个错误都是ESLint规则未适配Next.js 14的Server Action特性导致的:

  1. react/jsx-no-bind:这条规则原本是防止客户端React组件内联函数引发重渲染,但Next.js在Server Component中处理表单action时,会将内联Server Action编译为特殊的服务器端逻辑,不会触发客户端重渲染,ESLint未识别该场景。
  2. @typescript-eslint/no-misused-promises:规则默认认为原生表单action应接受返回void的函数,但Server Action是异步函数(返回Promise),Next.js内部已兼容该用法,ESLint规则未更新适配。

另外,你使用的eslint-config-next版本为13.2.4,与Next.js 14主版本不匹配,旧版本配置未包含Server Action的识别逻辑,这是核心问题。

解决方法

1. 升级ESLint配置适配Next.js 14

最彻底的解决方式是将eslint-config-next升级到与Next.js主版本一致的14.x.x:

npm install eslint-config-next@^14.0.3 --save-dev
# 或使用yarn
yarn add eslint-config-next@^14.0.3 --dev

升级后,Next.js的ESLint规则会自动识别Server Action用法,两个错误会自动消失。

2. 临时调整ESLint规则(不升级配置的情况)

若暂时不想升级,可在TypeScript文件的规则覆盖中添加例外:
修改eslintrc.js中TypeScript overrides的rules部分:

{
  files: "**/*.+(ts|tsx)",
  // ...其他配置
  rules: {
    // ...原有规则
    "@typescript-eslint/no-unused-vars": "error",
    "@typescript-eslint/no-explicit-any": "error",
    // 忽略原生DOM组件的内联函数,解决react/jsx-no-bind错误
    "react/jsx-no-bind": ["error", { ignoreDOMComponents: true }],
    // 允许属性接受返回Promise的函数,解决no-misused-promises错误
    "@typescript-eslint/no-misused-promises": [
      "error",
      {
        checksVoidReturn: {
          attributes: false,
        },
      },
    ],
  },
}

3. Server Action写法优化(可选)

内联写法本身没问题,但也可以将Server Action提取到组件外部,让代码结构更清晰:

// /app/search/page.tsx
async function updateResults(formData: FormData) {
  "use server";
  await new Promise((resolve) => setTimeout(resolve, 150));
  console.log("input value => ", formData.get("me"));
  revalidatePath("/search");
}

export default function Search() {
 return (
    <>
      <form action={updateResults}>
        <input name="me" type="text" />
        <button type="submit">Update</button>
      </form>
    </>
  )
}

关键结论

完全可以在Server Component中直接使用Server Action,不需要把表单放到Client Component里,这是Next.js 14官方支持的特性,错误仅由ESLint配置未适配导致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:15:55