Repository: jsx-eslint/eslint-plugin-react (JavaScript)

Issue:
react/prop-types does not validate missing propTypes for functions in version 7.17.0
Seems like this is still an issue in version 7.17.0

Missing prop types do not raise errors in a function component with a return of:

```
return (
    ordering.length > 0 && (
      <Paginator items={ordering} pageSize={10} />
    )
)
```

But do with a function component with a return of:

```
  if (ordering.length > 0) {
    return false;
  }

  return (
    <Paginator items={ordering} pageSize={10} />
  )
```

and:

```
  return ordering.length > 0 ? (
    <Paginator items={ordering} pageSize={10} />
  ) : null;
```
_Originally posted by @johnarnfield in https://github.com/yannickcr/eslint-plugin-react/issues/2134#issuecomment-566035325_


Discussion:

Patch:
diff --git a/lib/util/Components.js b/lib/util/Components.js
index c4334c8c0f..515a39dd00 100644
--- a/lib/util/Components.js
+++ b/lib/util/Components.js
@@ -46,6 +46,30 @@ function mergeUsedPropTypes(propsList, newPropsList) {
   return propsList.concat(propsToAdd);
 }
 
+function isReturnsConditionalJSX(node, property, strict) {
+  const returnsConditionalJSXConsequent = node[property] &&
+    node[property].type === 'ConditionalExpression' &&
+    jsxUtil.isJSX(node[property].consequent);
+  const returnsConditionalJSXAlternate = node[property] &&
+    node[property].type === 'ConditionalExpression' &&
+    jsxUtil.isJSX(node[property].alternate);
+  return strict ?
+    (returnsConditionalJSXConsequent && returnsConditionalJSXAlternate) :
+    (returnsConditionalJSXConsequent || returnsConditionalJSXAlternate);
+}
+
+function isReturnsLogicalJSX(node, property, strict) {
+  const returnsLogicalJSXLeft = node[property] &&
+    node[property].type === 'LogicalExpression' &&
+    jsxUtil.isJSX(node[property].left);
+  const returnsLogicalJSXRight = node[property] &&
+    node[property].type === 'LogicalExpression' &&
+    jsxUtil.isJSX(node[property].right);
+  return strict ?
+    (returnsLogicalJSXLeft && returnsLogicalJSXRight) :
+    (returnsLogicalJSXLeft || returnsLogicalJSXRight);
+}
+
 const Lists = new WeakMap();
 
 /**
@@ -373,22 +397,15 @@ function componentRule(rule, context) {
         return false;
       }
 
-      const returnsConditionalJSXConsequent = node[property] &&
-        node[property].type === 'ConditionalExpression' &&
-        jsxUtil.isJSX(node[property].consequent);
-      const returnsConditionalJSXAlternate = node[property] &&
-        node[property].type === 'ConditionalExpression' &&
-        jsxUtil.isJSX(node[property].alternate);
-      const returnsConditionalJSX = strict ?
-        (returnsConditionalJSXConsequent && returnsConditionalJSXAlternate) :
-        (returnsConditionalJSXConsequent || returnsConditionalJSXAlternate);
+      const returnsConditionalJSX = isReturnsConditionalJSX(node, property, strict);
+      const returnsLogicalJSX = isReturnsLogicalJSX(node, property, strict);
 
-      const returnsJSX = node[property] &&
-        jsxUtil.isJSX(node[property]);
+      const returnsJSX = node[property] && jsxUtil.isJSX(node[property]);
       const returnsPragmaCreateElement = this.isCreateElement(node[property]);
 
-      return Boolean(
+      return !!(
         returnsConditionalJSX ||
+        returnsLogicalJSX ||
         returnsJSX ||
         returnsPragmaCreateElement
       );


Test patch:
diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js
index b55fd6e0db..7f1ec41835 100755
--- a/tests/lib/rules/prop-types.js
+++ b/tests/lib/rules/prop-types.js
@@ -2465,6 +2465,19 @@ ruleTester.run('prop-types', rule, {
           pragma: 'Foo'
         }
       }
+    },
+    {
+      code: `
+        const Foo = ({length, ordering}) => (
+          length > 0 && (
+            <Paginator items={ordering} pageSize={10} />
+          )
+        );
+        Foo.propTypes = {
+          length: PropTypes.number,
+          ordering: PropTypes.array
+        };
+      `
     }
   ],
 
@@ -4895,6 +4908,21 @@ ruleTester.run('prop-types', rule, {
       errors: [{
         message: '\'foo.baz\' is missing in props validation'
       }]
+    },
+    {
+      code: `
+        const Foo = ({length, ordering}) => (
+          length > 0 && (
+            <Paginator items={ordering} pageSize={10} />
+          )
+        );
+      `,
+      errors: [{
+        message: '\'length\' is missing in props validation'
+      },
+      {
+        message: '\'ordering\' is missing in props validation'
+      }]
     }
   ]
 });