eslint-plugin-react: react/prop-types - is missing in props validation - false/positive when using inner function

Hi, I came across the issue with react/prop-types rule.

import React from 'react';
import PropTypes from "prop-types";

const DisplayName = (props) => {
    const getNameDiv = () => {
        return <div>{props.name}</div>;
    };

    return getNameDiv();
};

DisplayName.propTypes = {
    name: PropTypes.string.isRequired,
};

gives me warning 'name' is missing in props validation react/prop-types. Same thing happens if I rewrite function to function getNameDiv() {...}

After inlining getNameDiv there is no warning:

import React from 'react';
import PropTypes from "prop-types";

const DisplayName = (props) => {
    return <div>{props.name}</div>;
};

DisplayName.propTypes = {
    name: PropTypes.string.isRequired,
};

I was looking for similar issues but I didn’t find any. Maybe https://github.com/yannickcr/eslint-plugin-react/pull/1605 is connected?

I was using eslint-plugin-react: 7.11.1 but it’s the same for 7.13.3.

Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 22
  • Comments: 28 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Originally from https://stackoverflow.com/a/60510524/985454

I have discovered a strange behaviour. The only difference is in the return statement: enter image description here enter image description here

Now also the bar in propTypes is uncommented: enter image description here enter image description here

I think the problem is because the myFunc looks like a functional component and that eslint is picking it up wrongly.
enter image description here

Also, this is rather funny, if you simply rename the props to anything else, eslint goes silent 😃
enter image description here

Seems to be trigggered as soon as there’s not JSX returned? It just popped out of the blue for me…

// @flow

import * as React from 'react'

type Props = {
  tagName?: string,
  children: React.Node,
}

function Base({ tagName = 'div', children }: Props) {
  return React.createElement(tagName, {}, children)
}

Okay one could:

function Base({ tagName: Component = 'div', children }: Props) {
  return <Component>{children]</Component>
}

But still…

In this case, getNameDiv is actually being detected as a component (which it should be; prefer components to render functions).

I’m not sure how we could rule out getNameDiv as being a component without ruling out many valid use cases.

you shouldn’t be calling a function to return jsx, it should be a component

Not always. Making a component involves quite a lot of boilerplate; sometimes within a component it’s easier to use a simple inline function. I find it’s much better from a readability perspective to replace trees of ternary statements with a function containing a series of if/then statements.

This is pretty gross, especially with more conditions:

const thing = cond1 ? cond2 ? <Comp1/> : <Comp2/> : <Comp3/>;
return <div> ... a bunch of other stuff ... {thing}</div>;

This is more readable:

function thing() {
    if (cond1)
        if (cond2)
            return <Comp1/>;
        else
            return <Comp2/>;
     else
         return <Comp3/>;
}
return <div> ... a bunch of other stuff ... {thing()}</div>;

One of the nice things about working with jsx/tsx is that “it’s just javascript”. This lint rule rejects a common javascript idiom.

So I had 30 minutes to correct a bug at line 209 of material-ui-treeview. It’s a simple, one-file module with a permissive license, so I copied it into my code base and made the (trivial) change, then spent the next 19 minutes puzzling over how to remove this lint error before I disabled the rule for the module, then 5 minutes on the comment above. I’m referencing the specific file because I think it may provide a good concrete example of what I meant by “burdensome”. The location responsible for the errors (line 152) is a recursive function within a component; the function itself behaving as a component but needing its closure, and I couldn’t think of a quick way to refactor it to satisfy this rule. Further, it seemed to me that the design was suited to purpose, and any refactoring to eliminate the rule error would degrade the module’s design. This may be an exception case, and perhaps disabling the rule is the expected remedy, and I BTW agree that OP’s example is not ideal and think that detection of the anti-pattern is a good thing, but I also believe there’s a critical distinction between interface and implementation, and that the prop-types rule should be about interface, not implementation, because PropTypes is about interface, not implementation.

Certainly that’s subjective; personally I’d find it much more readable for noNames to be inline jsx, and for namesTable to be a separate component.

Let’s leave this open in case there’s a way to handle it.

Hello, This post can resolve your problem.

Look this: http://www.hackingwithreact.com/read/1/41/how-to-add-react-component-prop-validation-in-minutes

but he is using it in a deprecated way, to solve this.

Make this like:

function YourFunction ({params}) {
    
     return(
       {params}
      );

}

YourFunction.propTypes = { params: PropTypes.object.isRequired, };