26

I am trying to set up a typescript-react-eslint project and can't get past eslint error for this boilerplate component:

import * as React from "react";

interface ButtonProps {
  children?: React.ReactNode,
  onClick?: (e: any) => void,
}

const styles = {
  border: "1px solid #eee",
  borderRadius: 3,
  backgroundColor: "#FFFFFF",
  cursor: "pointer",
  fontSize: 15,
  padding: "3px 10px",
  margin: 10
};

const Button: React.FunctionComponent<ButtonProps> = props => (
  <button onClick={props.onClick} style={styles} type="button">
    {props.children}
  </button>
);

Button.defaultProps = {
  children: null,
  onClick: () => {}
};
export default Button;

The error is:

  19:26  error  'onClick' is missing in props validation   react/prop-types
  20:12  error  'children' is missing in props validation  react/prop-types

It seems like it is complaining about interface for html <button> is not defined? Otherwise it might be the Button component itself but should it not get type information from <ButtonProps> interface I pass there?

I tried explicitly setting children and onClick like this:

Button.propTypes = {
  children?: React.ReactNode,
  onClick?: (e: any) => void
};

it bypasses the eslint error but the component itself stops working. What am I doing wrong?

P.S. This is my .eslintrc.json

{
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true
    },
    "extends": [
        "eslint:recommended",
        "plugin:react/recommended",
        "plugin:@typescript-eslint/eslint-recommended"
    ],
    "globals": {
        "Atomics": "readonly",
        "SharedArrayBuffer": "readonly"
    },
    "settings": {
        "react": {
            "pragma": "React",
            "version": "detect"
        }
    },
    "parser": "@typescript-eslint/parser",
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": true
        },
        "ecmaVersion": 2018,
        "sourceType": "module"
    },
    "plugins": [
        "react",
        "@typescript-eslint"
    ],
    "rules": {
        "indent": [
            "error",
            2
        ],
        "linebreak-style": [
            "error",
            "unix"
        ],
        "quotes": [
            "error",
            "double"
        ],
        "semi": [
            "error",
            "always"
        ]
    }
}
MaxPY
  • 1,256
  • 4
  • 15
  • 30
  • Use default values inside arguments ` = ({ onClick: () => {}, children: null }) => (` – kind user Dec 15 '19 at 23:53
  • You don't need to define `children` in `ButtonProps` as `React.FunctionComponent` already defines it as: `children?: ReactNode`. Also, you can use `React.FC` instead of the very verbose `React.FunctionComponent` – JMadelaine Dec 16 '19 at 00:11
  • If I don't define children in `ButtonProps`, nothing changes: error still complains about both `children` and `onClick`. It seems like the interface is being ignored in `const Button: React.FC = props => ...` – MaxPY Dec 16 '19 at 00:17

4 Answers4

19

I ended up rewriting the component as:

const Button = ({ children, onClick }: ButtonProps) => {
  return <button onClick={onClick} style={styles} type="button">
    {children}
  </button>;
};

The : React.FC<ButtonProps> part was ignored by eslint so I decided to provide prop types in a more straightforward way

MaxPY
  • 1,256
  • 4
  • 15
  • 30
17

This rule doesn't make sense with TypeScript because you already is checking types.

In this question you found a simple way to disable this rule, just add in your eslint configuration:

  rules: {
    'react/prop-types': 0
  }

to be more readable you can use "off" instead "0".

João Bispo
  • 171
  • 2
  • 5
5

eslint-plugin-react@^7.25.0 appears to have resolved the issue for those using React.FC<IProps> with react/prop-types validation rule.

So instead of

const Example: React.FC<IProps> = (props: IProps) => ...

This now works without warnings after the update

const Example: React.FC<IProps> = (props) => ...
Sunnyok
  • 459
  • 11
  • 9
  • 1
    if we use a generic type for components, we can't use React.FC, and when passing props explicitly like `(props: Props) => `, the warning will be shown again – Bryan Lumbantobing Aug 13 '22 at 08:15
3

More info to your answer..

Firstly both ways are correct for declaring types, But React.FC has some added benefits. https://github.com/typescript-cheatsheets/react-typescript-cheatsheet/blob/master/README.md#function-components

enter image description here

And in your scenario you may be using eslint-react-plugin which has recommended rules 'plugin:react/recommended' for eslint ,
Rule to check proptypes is one among them, check typescript example. https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/prop-types.md

So react/prop-types rule will conflict with TS Interfaces, which is why it shows that error, once you add : ButtonProps, we don't have to provide React.FC

Hemanthvrm
  • 2,319
  • 1
  • 17
  • 26
  • 4
    FYI that page you linked to has been updated to say "the general consensus today is that React.FunctionComponent (or the shorthand React.FC) is discouraged" – David Gilbertson Mar 10 '21 at 00:04