Eslint-plugin-react: 'foo' is missing in props validation (react/prop-types)

Created on 25 Sep 2017  路  10Comments  路  Source: yannickcr/eslint-plugin-react

I was having trouble with this ('post' is missing in props validation (react/prop-types)):

export default Post = ({ post }) => (
  <div>{post.title}</div>
);

Post.propTypes = {
  post: PropTypes.arrayOf(PropTypes.object).isRequired,
};

but this did not have anymore issues:

const Post = ({ post }) => (
  <div>{post.title}</div>
);

Post.propTypes = {
  post: PropTypes.arrayOf(PropTypes.object).isRequired,
};

export default Post;

And I believe this information could be useful:

armenzg@armenzg-mbp readable-app$ node --version
v8.5.0
armenzg@armenzg-mbp readable-app$ ./node_modules/.bin/eslint --version
v4.7.2
armenzg@armenzg-mbp readable-app$ cat package.json | grep eslint
    "lint": "./node_modules/.bin/eslint src/",
    "eslint": "^4.7.2",
    "eslint-config-airbnb": "^15.1.0",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-jsx-a11y": "^5.1.1",
    "eslint-plugin-react": "^7.3.0"
armenzg@armenzg-mbp readable-app$ cat .eslintrc.js
module.exports = {
    "extends": "airbnb",
    "rules": {
      "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
      "no-undef": "off",
      "no-console": "off"
    }
};
bug help wanted

All 10 comments

I am having this issue in async functions

method1 = async () =>{
  const { propNotInPropTypes } = this.props
}

This does not show warning missing in props validation. And if i remove async, it works as expected.

@haikyuu that is a separate issue, but related to the same thing: the rule isn鈥檛 looking for those patterns. Could you file yours separately?

@ljharb done in #1583

The issue here is that variableUtil.variablesInScope(context) doesn't contain exports. So calling utils.getRelatedComponent() is unable to find Post from export default Post = ....
Not sure how correct it would be to make that function return exported identifiers. cc @ljharb

I'm not sure about the internals; but prop-types should be checking all components, whether exported or not (export modifies the module, not the value, so adding and removing export shouldn't change anything that's linted about the thing being exported)

Hmm, on further look I wasn't completely correct. variablesInScope does contain exports normally, which is why it all works out well in OP's second example. However, I think this

export default Post = () => ...

isn't the correct way to do default exports? There should be an expression, which in this case is an assignment expression, but Post doesn't get declared (no var/let/const). I think that explains why eslint-escope doesn't record it as a variable. So is this even valid ES2015, assigning to an undeclared variable (assuming strict mode in a module)?

Good catch - I don't think it is. @armenzg how were you able to avoid a syntax error here?

I'm going to close this, but will reopen if this is indeed valid.

FWIW (not sure if this is a good indicator of the real situation in this case) Babel transpiles this to

exports.default = Post = function Post() {};

and then

Post = function Post() {};

is a runtime ReferenceError in strict mode.

Let's close it.
If I hit it again I will create a test case on a repo.

Thanks for looking into it!

Was this page helpful?
0 / 5 - 0 ratings