208

I have the next code, eslint throw:

react/prop-types onClickOut; is missing in props validation

react/prop-types children; is missing in props validation

propTypes was defined but eslint does not recognize it.

import React, { Component, PropTypes } from 'react';

class IxClickOut extends Component {
  static propTypes = {
    children: PropTypes.any,
    onClickOut: PropTypes.func,
  };

 componentDidMount() {
    document.getElementById('app')
      .addEventListener('click', this.handleClick);
  }

  componentWillUnmount() {
    document.getElementById('app')
      .removeEventListener('click', this.handleClick);
  }

  handleClick = ({ target }: { target: EventTarget }) => {
    if (!this.containerRef.contains(target)) {
      this.props.onClickOut();
    }
  };

  containerRef: HTMLElement;

  render() {
    const { children, ...rest } = this.props;
    const filteredProps = _.omit(rest, 'onClickOut');

    return (
      <div
        {...filteredProps}
        ref={container => {
          this.containerRef = container;
        }}
      >
        {children}
      </div>
    );
  }
}

export default IxClickOut;

package.json

{
  "name": "verinmueblesmeteor",
  "private": true,
  "scripts": {
    "start": "meteor run",
    "ios": "NODE_ENV=developement meteor run ios"
  },
  "dependencies": {
    "fine-uploader": "^5.10.1",
    "foundation-sites": "^6.2.3",
    "install": "^0.8.1",
    "ix-gm-polygon": "^1.0.11",
    "ix-type-building": "^1.4.4",
    "ix-type-offer": "^1.0.10",
    "ix-utils": "^1.3.7",
    "keymirror": "^0.1.1",
    "meteor-node-stubs": "^0.2.3",
    "moment": "^2.13.0",
    "npm": "^3.10.3",
    "rc-slider": "^3.7.3",
    "react": "^15.1.0",
    "react-addons-pure-render-mixin": "^15.1.0",
    "react-dom": "^15.1.0",
    "react-fileupload": "^2.2.0",
    "react-list": "^0.7.18",
    "react-modal": "^1.4.0",
    "react-redux": "^4.4.5",
    "react-router": "^2.6.0",
    "react-styleable": "^2.2.4",
    "react-textarea-autosize": "^4.0.4",
    "redux": "^3.5.2",
    "redux-form": "^5.3.1",
    "redux-thunk": "^2.1.0",
    "rxjs": "^5.0.0-beta.9",
    "rxjs-es": "^5.0.0-beta.9",
    "socket.io": "^1.4.8"
  },
  "devDependencies": {
    "autoprefixer": "^6.3.6",
    "babel-eslint": "^6.0.4",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-preset-es2015": "^6.9.0",
    "babel-preset-react": "^6.5.0",
    "babel-preset-stage-0": "^6.5.0",
    "core-js": "^2.0.0",
    "cssnano": "^3.7.1",
    "eslint": "^2.12.0",
    "eslint-config-airbnb": "^9.0.1",
    "eslint-import-resolver-meteor": "^0.2.3",
    "eslint-plugin-import": "^1.8.1",
    "eslint-plugin-jsx-a11y": "^1.2.2",
    "eslint-plugin-react": "^5.1.1",
    "node-sass": "^3.8.0",
    "postcss-cssnext": "^2.6.0",
    "sasslets-animate": "0.0.4"
  },
  "cssModules": {
    "ignorePaths": [
      "node_modules"
    ],
    "jsClassNamingConvention": {
      "camelCase": true
    },
    "extensions": [
      "scss",
      "sass"
    ],
    "postcssPlugins": {
      "postcss-modules-values": {},
      "postcss-modules-local-by-default": {},
      "postcss-modules-extract-imports": {},
      "postcss-modules-scope": {},
      "autoprefixer": {}
    }
  }
}

.babelrc

{
  "presets": [
    "es2015",
    "react",
    "stage-0"
  ],
  "whitelist": [
      "es7.decorators",
      "es7.classProperties",
      "es7.exportExtensions",
      "es7.comprehensions",
      "es6.modules"
  ],
  "plugins": ["transform-decorators-legacy"]
}

.eslintrc

{
  "parser": "babel-eslint",
  "extends": "airbnb",
  "rules": {
    "no-underscore-dangle": ["error", { "allow": [_id, b_codes_id] }],
  },
  "settings": {
    "import/resolver": "meteor"
  },
  "globals": {
    "_": true,
    "CSSModule": true,
    "Streamy": true,
    "ReactClass": true,
    "SyntheticKeyboardEvent": true,
  }
}
Community
  • 1
  • 1

15 Answers15

132

You need to define propTypes as a static getter if you want it inside the class declaration:

static get propTypes() { 
    return { 
        children: PropTypes.any, 
        onClickOut: PropTypes.func 
    }; 
}

If you want to define it as an object, you need to define it outside the class, like this:

IxClickOut.propTypes = {
    children: PropTypes.any,
    onClickOut: PropTypes.func,
};

Also it's better if you import prop types from prop-types, not react, otherwise you'll see warnings in console (as preparation for React 16):

import PropTypes from 'prop-types';
Omri Aharon
  • 16,959
  • 5
  • 40
  • 58
  • 1
    Depends on the Babel config, it doesn't need to be a better if you're using the static properties plugin. – Dave Newton Jul 31 '16 at 14:42
  • Thanks. The first option throw the same error, the second option solve the problem but i dont understend why defining as class attribute throws an error in this case. Note: I have another components that work fine defining as class attribute – cristian camilo cedeño gallego Jul 31 '16 at 14:46
  • 1
    Not sure why one fails and the other one works. I thought it needed to be defined statically on a class either way, perhaps I was wrong. – Omri Aharon Jul 31 '16 at 14:47
130

I know this answer is ridiculous, but consider just disabling this rule until the bugs are worked out or you've upgraded your tooling:

/* eslint-disable react/prop-types */ // TODO: upgrade to latest eslint tooling

Or disable project-wide in your eslintrc:

"rules": {
  "react/prop-types": "off"
}
Devin Rhode
  • 23,026
  • 8
  • 58
  • 72
  • 2
    The actual syntax for disabling this rule is: "react/prop-types": "off" – Ken A Collins Dec 21 '20 at 15:37
  • Thanks this is also what I used in eslintrc under the rules section – iBobb Dec 22 '20 at 16:18
  • 3
    IMO, this is a bad practice and shouldn't be recommended to developers. Disabling rules can lead you down rabbit holes of writing poor code. (i.e. disabling rules whenever it seems more convenient.) – airvine Jan 28 '21 at 20:54
22

I ran into this issue over the past couple days. Like Omri Aharon said in their answer above, it is important to add definitions for your prop types similar to:

SomeClass.propTypes = {
    someProp: PropTypes.number,
    onTap: PropTypes.func,
};

Don't forget to add the prop definitions outside of your class. I would place it right below/above my class. If you are not sure what your variable type or suffix is for your PropType (ex: PropTypes.number), refer to this npm reference. To Use PropTypes, you must import the package:

import PropTypes from 'prop-types';

If you get the linting error:someProp is not required, but has no corresponding defaultProps declaration all you have to do is either add .isRequired to the end of your prop definition like so:

SomeClass.propTypes = {
    someProp: PropTypes.number.isRequired,
    onTap: PropTypes.func.isRequired,
};

OR add default prop values like so:

SomeClass.defaultProps = {
    someProp: 1
};

If you are anything like me, unexperienced or unfamiliar with reactjs, you may also get this error: Must use destructuring props assignment. To fix this error, define your props before they are used. For example:

const { someProp } = this.props;
airvine
  • 631
  • 8
  • 23
21

It seems that the problem is in eslint-plugin-react.

It can not correctly detect what props were mentioned in propTypes if you have annotated named objects via destructuring anywhere in the class.

There was similar problem in the past

Konstantin
  • 24,271
  • 5
  • 48
  • 65
9

Install prop-types package with- npm i prop-types --save Import it-

import PropTypes from 'prop-types';

Then specify the props, I implemented this way-

Text.propTypes = {
  children: PropTypes.node.isRequired,
};

export default function Text({ children }) {
  return (
    <VStyle className="para">
      <p>{children}</p>
    </VStyle> 
  );
}

Also add this in your eslintrc.json or .js file

"rules": {
    "react/prop-types": "off"
  }
Sathnindu Kottage
  • 1,083
  • 6
  • 17
6

On the new version of React and also Next.js, you can simply import PropTypes as follows,

import PropTypes from "prop-types";

and at the bottom of your file add defaultProps and propTypes such as,

Post.defaultProps = {
  posts: "",
};

Post.propTypes = {
  posts: PropTypes.string,
};

export default Post;

It should resolve your eslint warnings.

benjdan
  • 169
  • 2
  • 6
4

Issue: 'id1' is missing in props validation, eslintreact/prop-types

<div id={props.id1} >
    ...
</div>

Below solution worked, in a function component:

let { id1 } = props;

<div id={id1} >
    ...
</div>

Hope that helps.

Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
4

For me, upgrading eslint-plugin-react to the latest version 7.21.5 fixed this

Siphenathi
  • 491
  • 4
  • 7
4

PropTypes checking is a good thing, not recommend to ignore by settings

You can auto generate the propTypes by using vscode React PropTypes Generate extension:

  1. Select your Component's name
  2. Press command + . (Windows is Ctrl + .) show Code Actions and select PropTypesGenerate, or press shift + command + alt + P (Windows is shift + ctrl + alt + P) in the macOS
  3. Input propType to replace default type
Like
  • 131
  • 1
  • 1
3

Another way is:


File: App.js

    ...
        <Component1 key1="abc" />
    ...

File: Component1.js

1 error:

    function Component1 ({ key1 }) {
        console.log('key1', key1);
    }

2 error:

    function Component1 (props) {
        let{ key1 } = props;
        console.log('key1', key1);
    }

3 works:

NOTE: prop instead of props

    function Component1 (prop) {
        let{ key1 } = prop;
        console.log('key1', key1);
    }

Looks like, linter only checks for proper word props, not for prop or like.
It's a solution if you are just getting started or quick prototyping.
For later or large projects, defining proptypes might be better.


Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
2

the problem is in flow annotation in handleClick, i removed this and works fine thanks @alik

2

I'm finding eslint to be overly strict in the project I'm working on myself but for this error I fixed it by defining my interface and then implementing as such:

interface myInterface: {
  test: string
}

const MyComponent: React.FC<myInterface> = (props: myInterface) => {
edencorbin
  • 2,569
  • 5
  • 29
  • 44
2

Duplicating my answer from a similar question: https://stackoverflow.com/a/69199304/4290193

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
0

Functional React component. Defined as object. I got this error because I copied and pasted the object from a different with a slightly different name and forgot to change the name of the proptypes object.

FooterIcons.propTypes = {} -> FooterIcon.propTypes
thatguy1155
  • 102
  • 1
  • 8
0

Instead of disable prop-types rule, we can introduce children property as part of component props, eg:

import React, { Component } from 'react';

export default class ErrorBoundary extends Component<{ children: React.ReactNode }> {
  constructor(props: { children: React.ReactNode }) {
    super(props);

    this.state = { error: null, errorInfo: null };
  }

  componentDidCatch(error: Readonly<unknown>, errorInfo: Readonly<unknown>): void {
    this.setState({ error, errorInfo });
  }

  render(): React.ReactElement | React.ReactNode {
    const { children } = this.props;
    const { error, errorInfo } = this.state as Readonly<Record<string, { componentStack: string }>>;

    if (errorInfo)
      return (
        <details>
          <h3>Oops, error detected.</h3>
          <p>{error?.toString()}</p>
          <p>{errorInfo?.componentStack}</p>
        </details>
      );
    return children;
  }
}

Above one is typical example of getting eslint error gone ~~

Don't worry be happy ~~

DamonWu
  • 108
  • 3