Skip to content

Commit 3582d5f

Browse files
committed
New: Add require-default-props rule (fixes #528)
1 parent e67f3c5 commit 3582d5f

File tree

5 files changed

+1646
-0
lines changed

5 files changed

+1646
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Finally, enable all of the rules that you would like to use. Use [our preset](#
103103
* [react/prefer-stateless-function](docs/rules/prefer-stateless-function.md): Enforce stateless React Components to be written as a pure function
104104
* [react/prop-types](docs/rules/prop-types.md): Prevent missing props validation in a React component definition
105105
* [react/react-in-jsx-scope](docs/rules/react-in-jsx-scope.md): Prevent missing `React` when using JSX
106+
* [react/require-default-props](docs/rules/require-default-props.md): Enforce a defaultProps definition for every prop that is not a required prop
106107
* [react/require-optimization](docs/rules/require-optimization.md): Enforce React components to have a shouldComponentUpdate method
107108
* [react/require-render-return](docs/rules/require-render-return.md): Enforce ES5 or ES6 class for returning value in render function
108109
* [react/self-closing-comp](docs/rules/self-closing-comp.md): Prevent extra closing tags for components without children (fixable)

docs/rules/require-default-props.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Enforce a defaultProps definition for every prop that is not a required prop (require-default-props)
2+
3+
This rule aims to ensure that any non-required `PropType` declaration of a component has a corresponding `defaultProps` value.
4+
5+
One advantage of `defaultProps` over regular default logic in your code is that `defaultProps` are resolved by React before the `PropTypes` typechecking happens, so typechecking will also apply to your `defaultProps`.
6+
7+
To illustrate, consider the following example:
8+
9+
With `defaultProps`:
10+
```js
11+
const HelloWorld = ({ name }) => (
12+
<h1>Hello, {name.first} {name.last}!</h1>
13+
);
14+
15+
HelloWorld.propTypes = {
16+
name: React.PropTypes.shape({
17+
first: React.PropTypes.string,
18+
last: React.PropTypes.string,
19+
})
20+
};
21+
22+
HelloWorld.defaultProps = {
23+
name: 'john'
24+
};
25+
26+
// Logs:
27+
// Invalid prop `name` of type `string` supplied to `HelloWorld`, expected `object`.
28+
ReactDOM.render(<HelloWorld />, document.getElementById('app'));
29+
```
30+
31+
Without `defaultProps`:
32+
```js
33+
const HelloWorld = ({ name = 'John Doe' }) => (
34+
<h1>Hello, {name.first} {name.last}!</h1>
35+
);
36+
37+
HelloWorld.propTypes = {
38+
name: React.PropTypes.shape({
39+
first: React.PropTypes.string,
40+
last: React.PropTypes.string,
41+
})
42+
};
43+
44+
// Nothing is logged, renders:
45+
// "Hello,!"
46+
ReactDOM.render(<HelloWorld />, document.getElementById('app'));
47+
```
48+
49+
## Rule Details
50+
51+
The following patterns are considered warnings:
52+
53+
```js
54+
function MyStatelessComponent({ foo, bar }) {
55+
return <div>{foo}{bar}</div>;
56+
}
57+
58+
MyStatelessComponent.propTypes = {
59+
foo: React.PropTypes.string.isRequired,
60+
bar: React.PropTypes.string
61+
};
62+
```
63+
64+
```js
65+
var Greeting = React.createClass({
66+
render: function() {
67+
return <div>Hello {this.props.foo} {this.props.bar}</div>;
68+
},
69+
70+
propTypes: {
71+
foo: React.PropTypes.string,
72+
bar: React.PropTypes.string
73+
},
74+
75+
getDefaultProps: function() {
76+
return {
77+
foo: "foo"
78+
};
79+
}
80+
});
81+
```
82+
83+
```js
84+
class Greeting extends React.Component {
85+
render() {
86+
return (
87+
<h1>Hello, {this.props.foo} {this.props.bar}</h1>
88+
);
89+
}
90+
}
91+
92+
Greeting.propTypes = {
93+
foo: React.PropTypes.string,
94+
bar: React.PropTypes.string
95+
};
96+
97+
Greeting.defaultProps = {
98+
foo: "foo"
99+
};
100+
```
101+
102+
```js
103+
class Greeting extends React.Component {
104+
render() {
105+
return (
106+
<h1>Hello, {this.props.foo} {this.props.bar}</h1>
107+
);
108+
}
109+
110+
static propTypes = {
111+
foo: React.PropTypes.string,
112+
bar: React.PropTypes.string.isRequired
113+
};
114+
115+
static defaultProps = {
116+
foo: "foo"
117+
};
118+
}
119+
```
120+
121+
The following patterns are not considered warnings:
122+
123+
```js
124+
function MyStatelessComponent({ foo, bar }) {
125+
return <div>{foo}{bar}</div>;
126+
}
127+
128+
MyStatelessComponent.propTypes = {
129+
foo: React.PropTypes.string.isRequired,
130+
bar: React.PropTypes.string.isRequired
131+
};
132+
```
133+
134+
```js
135+
function MyStatelessComponent({ foo, bar }) {
136+
return <div>{foo}{bar}</div>;
137+
}
138+
139+
MyStatelessComponent.propTypes = {
140+
foo: React.PropTypes.string.isRequired,
141+
bar: React.PropTypes.string
142+
};
143+
144+
MyStatelessComponent.defaultProps = {
145+
bar: 'some default'
146+
};
147+
```
148+
149+
```js
150+
function NotAComponent({ foo, bar }) {}
151+
152+
NotAComponent.propTypes = {
153+
foo: React.PropTypes.string,
154+
bar: React.PropTypes.string.isRequired
155+
};
156+
```
157+
158+
## When Not To Use It
159+
160+
If you don't care about using `defaultsProps` for your component's props that are not required, you can disable this rule.
161+
162+
# Resources
163+
- [Official React documentation on defaultProps](https://facebook.github.io/react/docs/typechecking-with-proptypes.html#default-prop-values)

index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ var allRules = {
44
'jsx-uses-react': require('./lib/rules/jsx-uses-react'),
55
'no-multi-comp': require('./lib/rules/no-multi-comp'),
66
'prop-types': require('./lib/rules/prop-types'),
7+
'require-default-props': require('./lib/rules/require-default-props'),
78
'display-name': require('./lib/rules/display-name'),
89
'jsx-wrap-multilines': require('./lib/rules/jsx-wrap-multilines'),
910
'self-closing-comp': require('./lib/rules/self-closing-comp'),

0 commit comments

Comments
 (0)