与 TypeScript、React、Eslint 和简单的箭头函数组件苦斗

47

我整个早上都在努力解决这个问题,但无法在任何地方找到解决方案。我是 typescript 的新手,正在尝试使用 Eslint 和 Prettier 正确设置它,以确保代码格式正确。

所以,当我创建功能组件时遇到的问题是,根据“cheatsheet” ,我正在尝试导出一个简单的组件,例如:

import React from "react";

type DivProps = {
  text: string;
};

const Div = ({ text }: DivProps): JSX.Element => (<div>{text}</div>)

export default Div;

然而,eslint在抱怨,说“函数组件不是函数表达式”。

运行修复时,它将我的函数转换为一个无名函数:

const Div = function ({ text }: DivProps): JSX.Element {
  return <div>{text}</div>;
};

然后它会抱怨说“未预期的未命名函数”。

即使我尝试重构函数为:

function Div({ text }: DivProps): JSX.Element {
  return <div>{text}</div>;
};

我仍然收到相同的错误,提示“Function component is not a function expression”。

我的.eslintrc.js文件如下:

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: ["airbnb", "plugin:@typescript-eslint/recommended", "prettier"],
  parser: "@typescript-eslint/parser",
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: "module",
  },
  plugins: ["@typescript-eslint", "react-hooks", "prettier"],
  rules: {
    "react-hooks/rules-of-hooks": "error",
    "prettier/prettier": "error",
    "no-use-before-define": "off",
    "@typescript-eslint/no-use-before-define": ["error"],
    "react/jsx-filename-extension": [
      1,
      {
        extensions: [".tsx"],
      },
    ],
    "import/prefer-default-export": "off",
    "import/extensions": [
      "error",
      "ignorePackages",
      {
        ts: "never",
        tsx: "never",
      },
    ],
  },
  settings: {
    "import/resolver": {
      typescript: {},
    },
  },
};

希望能得到任何关于此事的帮助!

PS:如果您在 eslintrc 文件中看到任何需要修改/改进的地方,请让我知道。正如我所提到的,我是 TypeScript 的新手,因此仍在尝试找到最佳的代码检查选项。

谢谢!

Alejandro


你尝试过在函数组件中使用 FC 类型吗?const Div:FC<Props>=(props)=>null。你可以直接从 'react' 导入 FC - captain-yossarian from Ukraine
嗨,谢谢你的建议。不幸的是,它没有起作用。它一直抱怨一个函数组件不是一个函数表达式。 - Alejandro Aburto
尝试自动修复命令 - npm run lint -- --fix - Sarang Kakkoth
谢谢您的评论,但实际上解决方案是根据我下面的回复更改eslintrc文件。由于某种原因,在我的情况下,默认行为是更喜欢函数表达式,而根据文档应该是函数声明。无论如何,在eslintrc文件中指定选项解决了这个问题。 - Alejandro Aburto
5个回答

59

好的,所以我不知道这是否是正确答案,但最终更改Eslint的设置帮助我改变了组件函数的类型。我在我的.eslintrc.js文件中添加了以下规则:

"react/function-component-definition": [
  2,
  {
    namedComponents: "arrow-function",
    unnamedComponents: "arrow-function",
  },
],

有了这个设置,eslint只会接受箭头函数作为组件,而不是函数表达式(默认情况下)。


当你找到答案时,请告诉我们!但它已经起作用了!谢谢! - LuanLuanLuan
3
@LuanLuanLuan找到了答案(如果你没有关注这个问题),这其实是airbnb的代码检查规则中的一个bug。以下是我对这个问题的回答,更多细节请参考下面。 - slifty
@slifty 这个包 eslint-config-airbnb-typescript-prettier 怎么样? - user11720628
@chuklore,你需要向该软件包的维护者发出问题报告,要求他们更新设置,如果它仍在使用旧设置。同时,您可以遵循此问题的各种答案中提供的其他备选建议。 - slifty
嗨,@NamLêQuý,你有两个选择。你可以使用一个数组来表示这两个选项,例如 namedComponents: ["arrow-function", "function-declaration],或者你可以通过使用 "react/function-component-definition": [0] 来关闭此规则。希望这能帮到你。 - Alejandro Aburto
显示剩余2条评论

47

最终更新:已在eslint-config-airbnb版本19.0.4中进行了更正。

最好的做法是将您的软件包更新到19.0.4或更高版本。


过去的更新:这实际上是airbnb配置版本18.2.1到19.0.2中的一个错误

正确的设置应该是function-declaration,因此正确的解决方案是在您的.eslintrc.js中覆盖该规则。

"react/function-component-definition": [
  2,
  {
    namedComponents: "function-declaration",
  },
],

目前在airbnb的默认设置中,有一个未解决的PR现在已经合并了一个补丁,因此这个变化将使您的项目与预期的设置保持一致。

注意:您可能需要考虑导航到相关问题并为其投票,以便维护人员知道您正在处理它。

现在这个问题已经得到解决,您应该将版本更新至19.0.4或以上。

另一个选择:降级airbnb规则

正如另一个回答所提到的:如果您愿意,也可以将airbnb规则的版本降级至“坏”规则引入之前的版本(v18.2.1是没有这个规则的最新版本)。这可以通过更新您的package.json来完成:

"devDependencies": {
  ...
  "eslint-config-airbnb": "^18.2.1"
}

请注意,这意味着您的项目将不会使用最新的airbnb样式指南,因此您可能决定最好是覆盖规则。


我的先前回答,将根据代码检查器创建“有效”代码:

我也遇到了这个问题;我能够找出如何编写符合airbnb规则的代码,但是...我发现结果非常尴尬,而且我真的不知道为什么它会成为首选结果。

根据默认规则,您需要同时(A)使用函数表达式定义组件,但是(B)您不能使用匿名函数(这是为了防止堆栈跟踪中的“匿名函数”),因此还必须命名该函数:

const MyComponent = function MyComponent() { ... }

那么,以你的例子为例:

const Div = function Div({ text }: DivProps): JSX.Element {
  return <div>{text}</div>;
};

虽然这符合代码检查器的要求,但...哎呀,我说的对吧?


1
太棒了,感谢你的回答!你说得对,将函数声明指示在eslintrc文件中更符合Airbnb的样式规则。干杯! - Alejandro Aburto
这对我没有用,但Alejandro Aburto的有用。 - Ian
5
我有 eslint-config-airbnb 版本 19.0.4,出现了这个错误。 - romanown
1
@romanown 可能你面临另一个问题;请注意,如果你的代码仍然违反了代码规范,那么它需要被纠正!OP 的问题在于代码规范相互矛盾。现在这个问题已经不存在了。 - slifty
谢谢您。我添加了排除规则,现在一切都正常工作。 - romanown
显示剩余4条评论

7

它解决了我的问题,所以你可以尝试这个。

'react/function-component-definition': [
  2,
  {
    namedComponents: ['arrow-function', 'function-declaration'],
    unnamedComponents: 'arrow-function',
  },
],

3
我已经找到了克服这个问题的解决方案。基于@slifty的答案。如果您想同时支持"箭头函数"和"函数声明",请将值设置为字符串数组。考虑我的设置如下:

"react/function-component-definition": [
  "error",
  {
    "namedComponents": ["function-declaration", "arrow-function"],
    "unnamedComponents": "arrow-function"
  }
]

这个解决方案可与 "eslint-config-airbnb": "^19.0.4 一起使用。


2

1
我认为这应该被视为正确的答案,除非他们在提到的PR请求中修复它。 - user4164128
2
18.1是配置的旧版本——在引入错误规则之前——当然,人们可以降级。但如果目标是在新项目中使用最新设置,我建议使用19并手动修复此错误,直到补丁上线。 - slifty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接