prop-types doesn't seem to trigger when using https://facebook.github.io/react/blog/2015/09/10/react-v0.14-rc1.html#stateless-function-components
How could it? Stateless function components don't have a way of defining proptypes. It would be impossible for one to satisfy the rule.
The same way as adding to classes without using static
const Detaljer = ({ detaljer, feilkode }) => {
if (Array.isArray(detaljer)) {
return (
<ul>
{detaljer.map((detalj, i) => <li key={i}><Detalj detalj={detalj}/></li>)}
</ul>
);
}
return (
<div className="enkeltmelding">
<Detalj detalj={detaljer}/>
{feilkode ? <span className="kursiv-skrift">Feilkode: {feilkode}</span> : null}
</div>
);
};
Detaljer.propTypes = {
detaljer: PropTypes.string.isRequired,
feilkode: PropTypes.string,
removeEvent: PropTypes.string.isRequired
};

I did not know that stateless functions could have some propTypes like a regular component .
It is not supported by the plugin yet but I will work on it.
Hmmm. Neither did I. Good to know!
It's in the release notes as well :smile:
http://facebook.github.io/react/blog/2015/10/07/react-v0.14.html#stateless-functional-components
Functional components do not have lifecycle methods, but you can set .propTypes and .defaultProps as properties on the function.
Yeah I just saw that. I don't believe that was mentioned in the blogpost for 0.14 RC1. Now I'm going back and re-adding propTypes to my converted components.
I ran into this today; here is an example:

Thank you for all your great work @yannickcr! Your plugin has been very useful :)
I don't think eslint will ever be able to know the difference between a function that returns jsx and a React "stateless component", without a hint like a propTypes member.
Ah, sweet! Can't wait for the release :smile:
I hope it will works fine, like @dbrans said, it is hard to detect is we are in a stateless component. So I had to do some compromises (the function need to return some JSX or a call to React.createElement).
I will document it in the rule documentation.
the function need to return some JSX or a call to React.createElement
@yannickcr another method would be to check if the first parameter is props, as that would be almost always the case by convention.
(props) => {};
@gajus - what if someone does this:
({name, id}) => {};
FWIW, I've used this function in one of my codemods:
const isPossiblyPureComponent = path => {
if (path.parent.node.type === 'CallExpression')
return isPossiblyPureComponent(path.parent);
else if (path.parent.node.type === 'VariableDeclarator')
return true;
return false;
};
j(file.source)
.find(j.ArrowFunctionExpression)
.filter(
p => isPossiblyPureComponent(p)
&& (
p.node.body.type === 'JSXElement'
|| j(p.node.body)
.find(j.ReturnStatement)
.find(j.JSXElement)
.nodes()
.length
)
)
which did the trick of detecting Pure components pretty well, although it's I think too heavy
@yannickcr: Looks like you have the same conundrum as https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types/issues/1 (cc/ @oliviertassinari), which is that it's difficult to detect whether a function is in fact a stateless component. I see an elaborate method in https://github.com/reactjs/react-docgen/blob/713e848b80bc7e93778c4c6666d1cfde4d8e6e29/src/utils/isStatelessComponent.js, and I wonder if @fkling has any interest in making that a module of its own so other tools (like eslint-plugin-react and babel-plugin-transform-react-remove-prop-types) can use it. Any thoughts?
@yannickcr https://github.com/yannickcr/eslint-plugin-react/issues/237#issuecomment-149024842
Regarding the check of _should return some JSX_ -
I think I might have hit a minor bypass to the implementation of this check. The check works well when there is a return <some_jsx /> and thus the prop-types validation is run.
But if the function does something like below -
const returnValue = <some_jsx />;
....
return returnValue;
then it seems that the plugin doesn't recognize it as _returning some JSX_ and thus the prop-types validation is not run.
@prithsharma please file a new issue for that, and we can take a look
If you have no logic in your component you can even make it a bit more concise:
const MyComponent = (props) => (
<div>
<b>{props.firstname}</b>
</div>
);
MyComponent.propTypes = {
firstname: React.propTypes.string,
};
export default MyComponent;
Notice there is no return statement or curly brackets on the component.
(although then your component doesn't have an explicit name; it's best to use normal functions, not arrows, for SFCs)
@ljharb - If I'm not mistaken, theoretically you can do:
MyComponent.displayName = "MyComponent";
to retain the component name. Although it'll be writing characters to save a few characters ;)
Exactly right; but I'm also talking about the function's name property, which is useful for debugging, and more reliable when explicit.
If it helps someone, 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;
@armenzg that seems like a bug. Can you file that as a new issue?
@ljharb I've filed it:
https://github.com/yannickcr/eslint-plugin-react/issues/1447
Thanks!
I just had this issue and it turned out to be a typo that wasn't highlighted by ES Lint.
Problem:
import React from 'react'
import PropTypes from 'prop-types'
import { NavLink } from 'react-router-dom'
import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton'
// these two props were being highlighted as missing proptypes (which was actually true)
const ListActionsMenu = ({ thingRoute, serialNumber }) => {
const MENU_ITEMS = [
<li key='view'>
<MenuItem>
<NavLink to={`/${thingRoute}/view/${serialNumber}`}>View</NavLink>
</MenuItem>
</li>,
<li key='edit'>
<MenuItem>
<NavLink to={`/${thingRoute}/edit/${serialNumber}`}>Edit</NavLink>
</MenuItem>
</li>,
<li key='deactivate'>
<MenuItem>
<NavLink to={`/${thingRoute}/deactivate/${serialNumber}`}>Deactivate</NavLink>
</MenuItem>
</li>
]
return (
<Wrapper
className='list_results-actions'
onSelection={() => null}>
<Button className='list_results-actions-icon'>
<i className='fa fa-more-horiz' />
</Button>
<Menu className='list_results-actions-menu'>
<ul>{MENU_ITEMS}</ul>
</Menu>
</Wrapper>
)
}
// but, it was due to this capitalized P
ListActionsMenu.PropTypes = {
thingRoute: PropTypes.string.isRequired,
serialNumber: PropTypes.string.isRequired
}
export { ListActionsMenu }
@yannickcr @ljharb I figured I would just drop this example scenario in here, in case it is desired to analyze for any API hardening.
I was really confused why it was saying there was no prop types, and that would have been a 2 second fix if ES Lint had warned me that PropTypes needed a lower case p. I can see how it could be tricky to add a case for such anomalies though.
It could be nice to somehow get a red underline on Something.PropTypes = { if there is a capital P.
There鈥檚 already a no-typos rule that should handle that.
I also just ran into @amackintosh issue. I was able to trigger the typo detection by including react/no-typos in my .eslintrc.js file.
"rules": {
"react/no-typos": 1,
},
This seem to still be an issue. For stateful components missing prop-types are detected, but for a stateless functional component I get zero errors. eslint 5.12.0 and eslint-plugin-react 7.12.3.
I believe it has worked before, probably with an older React version, but I am not entirely sure. I was wondering if it could have something to do with multiple HOC wrappers, but both the functional and stateful components I am looking at are using more or less the same set of HOCs.
@ViggoV if so, please file a new issue with as much code and eslint output as possible.
Most helpful comment
The same way as adding to classes without using
static