React+TypeScript+Tailwind可复用Button组件适配ESLint问题求助
我是React、TypeScript、Tailwind及ESLint的新手,正在用这些技术构建项目,目前重点学习TypeScript和ESLint。原本创建了一个包含图标和文字的按钮,现在想改成可复用组件,参考过往JS组件经验尝试后没成功。后来参考文章代码实现组件,但粘贴到VSCode后ESLint报错Function component is not a function declaration。查看规则说明修改代码后,又出现Property 'FC' does not exist on type 'typeof React'.ts(2339)、Binding element 'children' implicitly has an 'any' type.ts(7031)等错误,多次调试无果。
组件代码
import React from 'react'; // interface to declare all our prop types interface Props { children: React.ReactNode; onClick: () => void; variant?: string, // default, primary, info, success, warning, danger, dark size?: string, // sm, md, lg disabled?: boolean; } // button component, consuming props const Button: React.FC<Props> = ({ children, onClick, variant = 'default', size = 'md', disabled, ...rest }) => { return ( <button className={`btn ${variant} ${size}` + (disabled ? ' disabled' : '')} onClick={onClick} disabled={disabled} {...rest} > {children} </button> ); }; export default Button;
修改后的错误代码片段
const Button = (React.FC<Props>) => ({
ESLint配置
module.exports = { env: { browser: true, es2021: true, }, extends: [ 'airbnb', 'airbnb/hooks', 'airbnb-typescript', 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', 'plugin:jsx-a11y/recommended', 'plugin:tailwindcss/recommended', ], overrides: [], parser: '@typescript-eslint/parser', parserOptions: { ecmaVersion: 'latest', sourceType: 'module', project: './tsconfig.json', }, plugins: ['react', '@typescript-eslint', 'prettier', 'jsx-a11y', 'tailwindcss'], rules: { 'react/react-in-jsx-scope': 0, 'react/prop-types': 0, 'react/require-default-props': 0, 'max-classes-per-file': 0, 'tailwindcss/no-custom-classname': 0, 'react/jsx-props-no-spreading': 0, 'prettier/prettier': [ 'warn', { endOfLine: 'crlf', }, {usePrettierrc: true}, ], }, };
解决方案
1. 解决Function component is not a function declaration错误
这个错误来自Airbnb的react/function-component-definition规则,默认要求函数组件使用函数声明形式,而非箭头函数赋值。你有两种解决方式:
方式一:改用函数声明
直接将组件改为函数声明格式,符合Airbnb规则要求:
import React from 'react'; interface Props { children: React.ReactNode; onClick: () => void; variant?: string; size?: string; disabled?: boolean; } // 改用函数声明形式 function Button({ children, onClick, variant = 'default', size = 'md', disabled, ...rest }: Props) { return ( <button className={`btn ${variant} ${size}${disabled ? ' disabled' : ''}`} onClick={onClick} disabled={disabled} {...rest} > {children} </button> ); } export default Button;
方式二:调整ESLint规则
如果偏好箭头函数写法,在ESLint配置的rules中添加规则,允许命名组件使用箭头函数:
'react/function-component-definition': [ 2, { namedComponents: 'arrow-function', }, ],
2. 解决Property 'FC' does not exist on type 'typeof React'错误
React 18+ 中React.FC不再作为默认导出的一部分,且官方更推荐直接为组件参数指定props类型(无需依赖FC)。如果仍想使用FC,需单独导入:
import React, { FC } from 'react'; // 之后可正常使用FC<Props> const Button: FC<Props> = ({ ... }) => { ... };
但更推荐的写法是直接给函数参数指定Props类型,如方式一中的代码,无需依赖FC。
3. 解决Binding element 'children' implicitly has an 'any' type错误
你修改后的代码是语法错误,正确的类型标注应该给函数参数指定类型,而非给箭头函数本身套FC类型。示例:
// 正确的箭头函数+类型标注写法 const Button = ({ children, onClick, variant = 'default', size = 'md', disabled, ...rest }: Props) => { // 组件逻辑 };
修正后的完整代码(函数声明+严谨类型版)
import React from 'react'; // 用字面量类型替代string,更符合TypeScript严谨性要求 interface Props { children: React.ReactNode; onClick: () => void; variant?: 'default' | 'primary' | 'info' | 'success' | 'warning' | 'danger' | 'dark'; size?: 'sm' | 'md' | 'lg'; disabled?: boolean; } function Button({ children, onClick, variant = 'default', size = 'md', disabled, ...rest }: Props) { return ( <button className={`btn ${variant} ${size}${disabled ? ' disabled' : ''}`} onClick={onClick} disabled={disabled} {...rest} > {children} </button> ); } export default Button;
内容的提问来源于stack exchange,提问作者Projektant42

