Skip to content

Commit 75ca44e

Browse files
committed
Merge pull request #250 from hamiltondanielb/master
Add prefer-es6-class rule (fixes #247)
2 parents 7bbbda7 + 06229ab commit 75ca44e

File tree

5 files changed

+123
-3
lines changed

5 files changed

+123
-3
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ Finally, enable all of the rules that you would like to use.
7373
"react/require-extension": 1,
7474
"react/self-closing-comp": 1,
7575
"react/sort-comp": 1,
76-
"react/wrap-multilines": 1
76+
"react/wrap-multilines": 1,
77+
"prefer-es6-class": 1,
7778
}
7879
}
7980
```
@@ -108,6 +109,7 @@ Finally, enable all of the rules that you would like to use.
108109
* [self-closing-comp](docs/rules/self-closing-comp.md): Prevent extra closing tags for components without children
109110
* [sort-comp](docs/rules/sort-comp.md): Enforce component methods order
110111
* [wrap-multilines](docs/rules/wrap-multilines.md): Prevent missing parentheses around multilines JSX
112+
* [prefer-es6-class](docs/rules/prefer-es6-class.md): Prefer es6 class instead of createClass for React Components
111113

112114
## To Do
113115

docs/rules/prefer-es6-class.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
ES6 class bodies are more terse than traditional object literals. Methods do not require a `function` keyword and no commas are needed to separate them. This refactoring looks as such:
2+
3+
Invalid:
4+
5+
```js
6+
var ExampleComponent = React.createClass({
7+
render: function() {
8+
return <div onClick={this._handleClick}>Hello, world.</div>;
9+
},
10+
_handleClick: function() {
11+
console.log(this);
12+
}
13+
});
14+
```
15+
16+
Valid:
17+
18+
```js
19+
class ExampleComponent extends React.Component {
20+
render() {
21+
return <div onClick={this._handleClick}>Hello, world.</div>;
22+
}
23+
_handleClick() {
24+
console.log(this);
25+
}
26+
}
27+
```

index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ module.exports = {
2929
'jsx-indent-props': require('./lib/rules/jsx-indent-props'),
3030
'jsx-closing-bracket-location': require('./lib/rules/jsx-closing-bracket-location'),
3131
'no-direct-mutation-state': require('./lib/rules/no-direct-mutation-state'),
32-
'forbid-prop-types': require('./lib/rules/forbid-prop-types')
32+
'forbid-prop-types': require('./lib/rules/forbid-prop-types'),
33+
'prefer-es6-class': require('./lib/rules/prefer-es6-class')
3334
},
3435
rulesConfig: {
3536
'jsx-uses-react': 0,
@@ -59,6 +60,7 @@ module.exports = {
5960
'jsx-indent-props': 0,
6061
'jsx-closing-bracket-location': 0,
6162
'no-direct-mutation-state': 0,
62-
'forbid-prop-types': 0
63+
'forbid-prop-types': 0,
64+
'prefer-es6-class': 0
6365
}
6466
};

lib/rules/prefer-es6-class.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @fileoverview Prefer es6 class instead of createClass for React Component
3+
* @author Dan Hamilton
4+
*/
5+
'use strict';
6+
7+
var componentUtil = require('../util/component');
8+
9+
// ------------------------------------------------------------------------------
10+
// Rule Definition
11+
// ------------------------------------------------------------------------------
12+
13+
module.exports = function(context) {
14+
15+
return {
16+
ObjectExpression: function(node) {
17+
if (componentUtil.isComponentDefinition(context, node)) {
18+
context.report(node, 'Component should use es6 class instead of createClass');
19+
}
20+
}
21+
};
22+
};
23+
24+
module.exports.schema = [];

tests/lib/rules/prefer-es6-class.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @fileoverview Prefer es6 class instead of createClass for React Component
3+
* @author Dan Hamilton
4+
*/
5+
'use strict';
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var rule = require('../../../lib/rules/prefer-es6-class');
12+
var RuleTester = require('eslint').RuleTester;
13+
14+
require('babel-eslint');
15+
16+
// ------------------------------------------------------------------------------
17+
// Tests
18+
// ------------------------------------------------------------------------------
19+
20+
var ruleTester = new RuleTester();
21+
ruleTester.run('prefer-es6-class', rule, {
22+
23+
valid: [{
24+
code: [
25+
'class Hello extends React.Component {',
26+
' render() {',
27+
' return <div>Hello {this.props.name}</div>;',
28+
' }',
29+
'}',
30+
'Hello.displayName = \'Hello\''
31+
].join('\n'),
32+
ecmaFeatures: {
33+
classes: true,
34+
jsx: true
35+
}
36+
}, {
37+
code: [
38+
'var Hello = "foo";',
39+
'module.exports = {};'
40+
].join('\n'),
41+
ecmaFeatures: {
42+
jsx: true
43+
}
44+
}
45+
46+
],
47+
48+
invalid: [{
49+
code: [
50+
'var Hello = React.createClass({',
51+
' displayName: \'Hello\',',
52+
' render: function() {',
53+
' return <div>Hello {this.props.name}</div>;',
54+
' }',
55+
'});'
56+
].join('\n'),
57+
ecmaFeatures: {
58+
classes: true,
59+
jsx: true
60+
},
61+
errors: [{
62+
message: 'Component should use es6 class instead of createClass'
63+
}]
64+
}
65+
]});

0 commit comments

Comments
 (0)