Skip to content

Commit 13fddef

Browse files
author
Haridu Senadeera
committed
add lifecycle method typos
1 parent 2d2cf65 commit 13fddef

File tree

3 files changed

+155
-3
lines changed

3 files changed

+155
-3
lines changed

docs/rules/no-typos.md

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,31 @@
11
# Prevents common casing typos (react/no-typos)
22

3-
Ensure no casing typos were made declaring static class properties
3+
Ensure no casing typos were made declaring static class properties and lifecycle methods.
44

55
## Rule Details
66

7-
This rule checks whether the declared static class properties related to React components
8-
do not contain any typos. It currently makes sure that the following class properties have
7+
This rule checks whether the declared static class properties and lifecycle methods related to React components
8+
do not contain any typos.
9+
10+
It currently makes sure that the following class properties have
911
no casing typos:
1012

1113
* propTypes
1214
* contextTypes
1315
* childContextTypes
1416
* defaultProps
1517

18+
and the following react lifecycle methods:
19+
20+
* componentWillMount
21+
* componentDidMount
22+
* componentWillReceiveProps
23+
* shouldComponentUpdate
24+
* componentWillUpdate
25+
* componentDidUpdate
26+
* componentWillUnmount
27+
28+
1629
The following patterns are considered warnings:
1730

1831
```js
@@ -47,6 +60,18 @@ class MyComponent extends React.Component {
4760
class MyComponent extends React.Component {
4861
static defaultprops = {}
4962
}
63+
64+
class MyComponent extends React.Component {
65+
componentwillMount() {}
66+
}
67+
68+
class MyComponent extends React.Component {
69+
ComponentWillReceiveProps() {}
70+
}
71+
72+
class MyComponent extends React.Component {
73+
componentdidupdate() {}
74+
}
5075
```
5176

5277
The following patterns are not considered warnings:
@@ -67,4 +92,16 @@ class MyComponent extends React.Component {
6792
class MyComponent extends React.Component {
6893
static defaultProps = {}
6994
}
95+
96+
class MyComponent extends React.Component {
97+
componentWillMount() {}
98+
}
99+
100+
class MyComponent extends React.Component {
101+
componentWillReceiveProps() {}
102+
}
103+
104+
class MyComponent extends React.Component {
105+
componentDidUpdate() {}
106+
}
70107
```

lib/rules/no-typos.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ const Components = require('../util/Components');
1010
// ------------------------------------------------------------------------------
1111

1212
const STATIC_CLASS_PROPERTIES = ['propTypes', 'contextTypes', 'childContextTypes', 'defaultProps'];
13+
const LIFECYCLE_METHODS = [
14+
'componentWillMount',
15+
'componentDidMount',
16+
'componentWillReceiveProps',
17+
'shouldComponentUpdate',
18+
'componentWillUpdate',
19+
'componentDidUpdate',
20+
'componentWillUnmount'
21+
];
1322

1423
module.exports = {
1524
meta: {
@@ -33,6 +42,17 @@ module.exports = {
3342
});
3443
}
3544

45+
function reportErrorIfLifecycleMethodCasingTypo(node) {
46+
LIFECYCLE_METHODS.forEach(function(method) {
47+
if (method.toLowerCase() === node.key.name.toLowerCase() && method !== node.key.name) {
48+
context.report({
49+
node: node,
50+
message: 'Typo in component lifecycle method declaration'
51+
});
52+
}
53+
});
54+
}
55+
3656
return {
3757
ClassProperty: function(node) {
3858
if (!node.static || !utils.isES6Component(node.parent.parent)) {
@@ -54,6 +74,14 @@ module.exports = {
5474
const propertyName = node.property.name;
5575
reportErrorIfCasingTypo(node, propertyName);
5676
}
77+
},
78+
79+
MethodDefinition: function (node) {
80+
if (!utils.isES6Component(node.parent.parent) || utils.isReturningJSX(node.parent.parent)) {
81+
return;
82+
}
83+
84+
reportErrorIfLifecycleMethodCasingTypo(node);
5785
}
5886
};
5987
})

tests/lib/rules/no-typos.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const parserOptions = {
2222
// -----------------------------------------------------------------------------
2323

2424
const ERROR_MESSAGE = 'Typo in static class property declaration';
25+
const ERROR_MESSAGE_LIFECYCLE_METHOD = 'Typo in component lifecycle method declaration';
2526

2627
const ruleTester = new RuleTester();
2728
ruleTester.run('no-typos', rule, {
@@ -181,6 +182,49 @@ ruleTester.run('no-typos', rule, {
181182
'First[defautProps] = {};'
182183
].join('\n'),
183184
parserOptions: parserOptions
185+
}, {
186+
code: [
187+
'class Hello extends React.Component {',
188+
' componentDidUpdate() { }',
189+
' render() {',
190+
' return <div>Hello {this.props.name}</div>;',
191+
' }',
192+
'}'
193+
].join('\n'),
194+
parserOptions: parserOptions
195+
}, {
196+
code: [
197+
'class Hello extends React.Component {',
198+
' componentWillMount() { }',
199+
' componentDidUpdate() { }',
200+
' render() {',
201+
' return <div>Hello {this.props.name}</div>;',
202+
' }',
203+
'}'
204+
].join('\n'),
205+
parserOptions: parserOptions
206+
}, {
207+
code: [
208+
'class Hello extends React.Component {',
209+
' componentWillUnmount() { }',
210+
' componentWillMount() { }',
211+
' render() {',
212+
' return <div>Hello {this.props.name}</div>;',
213+
' }',
214+
'}'
215+
].join('\n'),
216+
parserOptions: parserOptions
217+
}, {
218+
code: [
219+
'class Hello extends React.Component {',
220+
' shouldComponentUpdate() { }',
221+
' componentWillReceiveProps() { }',
222+
' render() {',
223+
' return <div>Hello {this.props.name}</div>;',
224+
' }',
225+
'}'
226+
].join('\n'),
227+
parserOptions: parserOptions
184228
}],
185229

186230
invalid: [{
@@ -367,5 +411,48 @@ ruleTester.run('no-typos', rule, {
367411
].join('\n'),
368412
parserOptions: parserOptions,
369413
errors: [{message: ERROR_MESSAGE}]
414+
}, {
415+
code: [
416+
'class Hello extends React.Component {',
417+
' ComponentDidUpdate() { }',
418+
' render() {',
419+
' return <div>Hello {this.props.name}</div>;',
420+
' }',
421+
'}'
422+
].join('\n'),
423+
parserOptions: parserOptions,
424+
errors: [{
425+
message: ERROR_MESSAGE_LIFECYCLE_METHOD,
426+
type: 'MethodDefinition'
427+
}]
428+
}, {
429+
code: [
430+
'class Hello extends React.Component {',
431+
' componentwillreceiveprops() { }',
432+
' render() {',
433+
' return <div>Hello {this.props.name}</div>;',
434+
' }',
435+
'}'
436+
].join('\n'),
437+
parserOptions: parserOptions,
438+
errors: [{
439+
message: ERROR_MESSAGE_LIFECYCLE_METHOD,
440+
type: 'MethodDefinition'
441+
}]
442+
}, {
443+
code: [
444+
'class Hello extends React.Component {',
445+
' componentWillReceiveProps() { }',
446+
' componentWillupdate() { }',
447+
' render() {',
448+
' return <div>Hello {this.props.name}</div>;',
449+
' }',
450+
'}'
451+
].join('\n'),
452+
parserOptions: parserOptions,
453+
errors: [{
454+
message: ERROR_MESSAGE_LIFECYCLE_METHOD,
455+
type: 'MethodDefinition'
456+
}]
370457
}]
371458
});

0 commit comments

Comments
 (0)