Skip to content

Commit 4f3cd90

Browse files
RedTnljharb
authored andcommitted
[New] require-default-props: add option to ignore functional components
1 parent 0d7019b commit 4f3cd90

File tree

4 files changed

+400
-5
lines changed

4 files changed

+400
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
1111
* [`prop-types`][]: Support Flow Type spread ([#2446][] @moroine)
1212
* [`jsx-props-no-spreading`][]: add `explicitSpread` option to allow explicit spread of props ([#2449][] @pawelnvk)
1313
* [`jsx-no-target-blank`][]: warn on `target={'_blank'}` expressions ([#2451][] @timkraut)
14+
* [`require-default-props`]: add option to ignore functional components ([#2532][] @RedTn)
1415

1516
### Fixed
1617
* [`sort-prop-types`][], [`jsx-sort-default-props`][]: disable broken autofix ([#2505][] @webOS101)
@@ -34,6 +35,7 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
3435
* [Docs] [`no-unused-prop-types`][]: clean up prose ([#2273][] @coryhouse)
3536
* [Docs] [`jsx-no-bind`][]: add section about React Hooks ([#2443][] @kdex)
3637

38+
[#2532]: https://github.com/yannickcr/eslint-plugin-react/pull/2532
3739
[#2505]: https://github.com/yannickcr/eslint-plugin-react/pull/2505
3840
[#2504]: https://github.com/yannickcr/eslint-plugin-react/pull/2504
3941
[#2500]: https://github.com/yannickcr/eslint-plugin-react/pull/2500

docs/rules/require-default-props.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,13 @@ NotAComponent.propTypes = {
188188

189189
```js
190190
...
191-
"react/require-default-props": [<enabled>, { forbidDefaultForRequired: <boolean> }]
191+
"react/require-default-props": [<enabled>, { forbidDefaultForRequired: <boolean>, ignoreFunctionalComponents: <boolean> }]
192192
...
193193
```
194194

195195
* `enabled`: for enabling the rule. 0=off, 1=warn, 2=error. Defaults to 0.
196196
* `forbidDefaultForRequired`: optional boolean to forbid prop default for a required prop. Defaults to false.
197+
* `ignoreFunctionalComponents`: optional boolean to ignore this rule for functional components. Defaults to false.
197198

198199
### `forbidDefaultForRequired`
199200

@@ -269,6 +270,67 @@ MyStatelessComponent.propTypes = {
269270
};
270271
```
271272

273+
### `ignoreFunctionalComponents`
274+
275+
When set to `true`, ignores this rule for all functional components.
276+
277+
The following patterns are warnings:
278+
279+
```jsx
280+
class Greeting extends React.Component {
281+
render() {
282+
return (
283+
<h1>Hello, {this.props.foo} {this.props.bar}</h1>
284+
);
285+
}
286+
287+
static propTypes = {
288+
foo: PropTypes.string,
289+
bar: PropTypes.string.isRequired
290+
};
291+
292+
static defaultProps = {
293+
foo: "foo",
294+
bar: "bar"
295+
};
296+
}
297+
```
298+
299+
The following patterns are **not** warnings:
300+
301+
```jsx
302+
function MyStatelessComponent({ foo, bar }) {
303+
return <div>{foo}{bar}</div>;
304+
}
305+
306+
MyStatelessComponent.propTypes = {
307+
foo: PropTypes.string,
308+
bar: PropTypes.string
309+
};
310+
```
311+
312+
```jsx
313+
const MyStatelessComponent = ({ foo, bar }) => {
314+
return <div>{foo}{bar}</div>;
315+
}
316+
317+
MyStatelessComponent.propTypes = {
318+
foo: PropTypes.string,
319+
bar: PropTypes.string
320+
};
321+
```
322+
323+
```jsx
324+
const MyStatelessComponent = function({ foo, bar }) {
325+
return <div>{foo}{bar}</div>;
326+
}
327+
328+
MyStatelessComponent.propTypes = {
329+
foo: PropTypes.string,
330+
bar: PropTypes.string
331+
};
332+
```
333+
272334
## When Not To Use It
273335

274336
If you don't care about using `defaultsProps` for your component's props that are not required, you can disable this rule.

lib/rules/require-default-props.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
const Components = require('../util/Components');
99
const docsUrl = require('../util/docsUrl');
10-
10+
const astUtil = require('../util/ast');
1111

1212
// ------------------------------------------------------------------------------
1313
// Rule Definition
@@ -26,6 +26,9 @@ module.exports = {
2626
properties: {
2727
forbidDefaultForRequired: {
2828
type: 'boolean'
29+
},
30+
ignoreFunctionalComponents: {
31+
type: 'boolean'
2932
}
3033
},
3134
additionalProperties: false
@@ -35,7 +38,7 @@ module.exports = {
3538
create: Components.detect((context, components) => {
3639
const configuration = context.options[0] || {};
3740
const forbidDefaultForRequired = configuration.forbidDefaultForRequired || false;
38-
41+
const ignoreFunctionalComponents = configuration.ignoreFunctionalComponents || false;
3942

4043
/**
4144
* Reports all propTypes passed in that don't have a defaultProps counterpart.
@@ -83,7 +86,13 @@ module.exports = {
8386
'Program:exit'() {
8487
const list = components.list();
8588

86-
Object.keys(list).filter(component => list[component].declaredPropTypes).forEach((component) => {
89+
Object.keys(list).filter((component) => {
90+
if (ignoreFunctionalComponents &&
91+
(astUtil.isFunction(list[component].node) || astUtil.isFunctionLikeExpression(list[component].node))) {
92+
return false;
93+
}
94+
return list[component].declaredPropTypes;
95+
}).forEach((component) => {
8796
reportPropTypesWithoutDefault(
8897
list[component].declaredPropTypes,
8998
list[component].defaultProps || {}

0 commit comments

Comments
 (0)