Skip to content

Commit 4c8dee4

Browse files
feat: mapStateToProps/mapDispatchToProps-prefer-parameters-names supporting more cases (#8)
* feat: [mapStateToProps-prefer-parameters-names] supporting more cases * feat: [mapDispatchToProps-prefer-parameters-names] supporting more cases * fix: extra safe guards
1 parent a746361 commit 4c8dee4

11 files changed

+123
-27
lines changed

docs/rules/mapDispatchToProps-prefer-parameters-names.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ The following pattern is considered incorrect:
1414
const mapDispatchToProps = (anyOtherName) => {}
1515
```
1616

17+
```js
18+
connect((state) => state, (anyOtherName) => {})(App)
19+
```
20+
1721
The following patterns are considered correct:
1822

1923
```js
@@ -27,3 +31,7 @@ const mapDispatchToProps(dispatch, ownProps) => {}
2731
```js
2832
const mapDispatchToProps(dispatch) => {}
2933
```
34+
35+
```js
36+
connect((state) => state, (dispatch, ownProps, moreArgs) => {})(App)
37+
```

docs/rules/mapStateToProps-prefer-parameters-names.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ The following pattern is considered incorrect:
1414
const mapStateToProps = (anyOtherName) => {}
1515
```
1616

17+
```js
18+
connect(function(anyOtherName) {}, null)(App)
19+
```
20+
1721
The following patterns are considered correct:
1822

1923
```js
@@ -23,3 +27,7 @@ const mapStateToProps = (state, ownProps) => {}
2327
```js
2428
const mapStateToProps = (state) => {}
2529
```
30+
31+
```js
32+
connect((state) => state, null)(App)
33+
```

lib/rules/mapDispatchToProps-prefer-object.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ module.exports = function (context) {
3030
CallExpression(node) {
3131
if (isReactReduxConnect(node)) {
3232
const mapDispatchToProps = node.arguments && node.arguments[1];
33-
if (mapDispatchToProps.type === 'ArrowFunctionExpression' ||
34-
mapDispatchToProps.type === 'FunctionExpression'
33+
if (mapDispatchToProps && (
34+
mapDispatchToProps.type === 'ArrowFunctionExpression' ||
35+
mapDispatchToProps.type === 'FunctionExpression')
3536
) {
3637
report(context, mapDispatchToProps);
3738
}
Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const isReactReduxConnect = require('../isReactReduxConnect');
2+
13
const argumentNames = [
24
'dispatch',
35
'ownProps',
@@ -10,22 +12,43 @@ const report = function (context, node, i) {
1012
});
1113
};
1214

13-
const checkDeclaration = function (context, node) {
14-
if (node.id && node.id.name === 'mapDispatchToProps'
15-
&& node.init && node.init.params
16-
) {
17-
node.init.params.forEach((param, i) => {
18-
if (argumentNames[i] && argumentNames[i] !== param.name) {
19-
report(context, param, i);
20-
}
21-
});
22-
}
15+
const check = function (context, params) {
16+
params.forEach((param, i) => {
17+
if (argumentNames[i] && argumentNames[i] !== param.name) {
18+
report(context, param, i);
19+
}
20+
});
2321
};
2422

2523
module.exports = function (context) {
2624
return {
2725
VariableDeclaration(node) {
28-
node.declarations.forEach(decl => checkDeclaration(context, decl));
26+
node.declarations.forEach((decl) => {
27+
if (decl.id && decl.id.name === 'mapDispatchToProps') {
28+
if (decl.init && (
29+
decl.init.type === 'ArrowFunctionExpression' ||
30+
decl.init.type === 'FunctionExpression'
31+
)) {
32+
check(context, decl.init.params);
33+
}
34+
}
35+
});
36+
},
37+
FunctionDeclaration(node) {
38+
if (node.id && node.id.name === 'mapDispatchToProps') {
39+
check(context, node.params);
40+
}
41+
},
42+
CallExpression(node) {
43+
if (isReactReduxConnect(node)) {
44+
const mapDispatchToProps = node.arguments && node.arguments[1];
45+
if (mapDispatchToProps && (
46+
mapDispatchToProps.type === 'ArrowFunctionExpression' ||
47+
mapDispatchToProps.type === 'FunctionExpression')
48+
) {
49+
check(context, mapDispatchToProps.params);
50+
}
51+
}
2952
},
3053
};
3154
};

lib/rules/mapStateToProps-no-store.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ module.exports = function (context) {
4646
CallExpression(node) {
4747
if (isReactReduxConnect(node)) {
4848
const mapStateToProps = node.arguments && node.arguments[0];
49-
if (mapStateToProps.body) {
49+
if (mapStateToProps && mapStateToProps.body) {
5050
checkFunction(context, mapStateToProps.body, getFirstParamName(mapStateToProps));
5151
}
5252
}
Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
const isReactReduxConnect = require('../isReactReduxConnect');
2+
13
const argumentNames = [
24
'state',
35
'ownProps',
@@ -10,22 +12,43 @@ const report = function (context, node, i) {
1012
});
1113
};
1214

13-
const checkDeclaration = function (context, node) {
14-
if (node.id && node.id.name === 'mapStateToProps'
15-
&& node.init && node.init.params
16-
) {
17-
node.init.params.forEach((param, i) => {
18-
if (argumentNames[i] && argumentNames[i] !== param.name) {
19-
report(context, param, i);
20-
}
21-
});
22-
}
15+
const check = function (context, params) {
16+
params.forEach((param, i) => {
17+
if (argumentNames[i] && argumentNames[i] !== param.name) {
18+
report(context, param, i);
19+
}
20+
});
2321
};
2422

2523
module.exports = function (context) {
2624
return {
2725
VariableDeclaration(node) {
28-
node.declarations.forEach(decl => checkDeclaration(context, decl));
26+
node.declarations.forEach((decl) => {
27+
if (decl.id && decl.id.name === 'mapStateToProps') {
28+
if (decl.init && (
29+
decl.init.type === 'ArrowFunctionExpression' ||
30+
decl.init.type === 'FunctionExpression'
31+
)) {
32+
check(context, decl.init.params);
33+
}
34+
}
35+
});
36+
},
37+
FunctionDeclaration(node) {
38+
if (node.id && node.id.name === 'mapStateToProps') {
39+
check(context, node.params);
40+
}
41+
},
42+
CallExpression(node) {
43+
if (isReactReduxConnect(node)) {
44+
const mapStateToProps = node.arguments && node.arguments[0];
45+
if (mapStateToProps && (
46+
mapStateToProps.type === 'ArrowFunctionExpression' ||
47+
mapStateToProps.type === 'FunctionExpression')
48+
) {
49+
check(context, mapStateToProps.params);
50+
}
51+
}
2952
},
3053
};
3154
};

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
"scripts": {
1414
"lint": "eslint ./",
1515
"test": "npm run lint && mocha tests --recursive",
16-
"test-single": "mocha tests/lib/rules/mapDispatchToProps-prefer-object",
17-
"debug-test": "mocha --debug-brk --inspect tests/lib/rules/mapDispatchToProps-prefer-object",
16+
"test-single": "mocha tests/lib/rules/mapStateToProps-prefer-parameters-names",
17+
"debug-test": "mocha --debug-brk --inspect tests/lib/rules/mapStateToProps-prefer-parameters-names",
1818
"semantic-release": "semantic-release",
1919
"commitmsg": "npm run test && commitlint -e $GIT_PARAMS"
2020
},

tests/lib/rules/mapDispatchToProps-prefer-object.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ruleTester.run('mapDispatchToProps-prefer-object', rule, {
2323
{ fetchProducts }
2424
)(Products);
2525
`,
26+
'connect(null, null)(App)',
2627
],
2728
invalid: [{
2829
code: 'function mapDispatchToProps () {}',

tests/lib/rules/mapDispatchToProps-prefer-parameters-names.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ ruleTester.run('mapDispatchToProps-prefer-parameters-names', rule, {
1919
'const mapDispatchToProps = (dispatch) => {}',
2020
'const mapDispatchToProps = (dispatch, ownProps, moreArgs) => {}',
2121
'const mapDispatchToProps = {anAction: anAction}',
22+
'connect((state) => state, {anAction: anAction})(App)',
23+
'connect(null, null)(App)',
24+
'connect((state) => state, (dispatch, ownProps, moreArgs) => {})(App)',
25+
'function mapDispatchToProps(dispatch, ownProps) {}',
26+
2227
],
2328
invalid: [{
2429
code: 'const mapDispatchToProps = (anyOtherName) => {}',
@@ -36,5 +41,19 @@ ruleTester.run('mapDispatchToProps-prefer-parameters-names', rule, {
3641
message: 'mapDispatchToProps function parameter #1 should be named ownProps',
3742
},
3843
],
44+
}, {
45+
code: 'function mapDispatchToProps(anyOtherName) {}',
46+
errors: [
47+
{
48+
message: 'mapDispatchToProps function parameter #0 should be named dispatch',
49+
},
50+
],
51+
}, {
52+
code: 'connect((state) => state, (anyOtherName) => {})(App)',
53+
errors: [
54+
{
55+
message: 'mapDispatchToProps function parameter #0 should be named dispatch',
56+
},
57+
],
3958
}],
4059
});

tests/lib/rules/mapStateToProps-no-store.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ ruleTester.run('mapStateToProps-no-store', rule, {
2020
'export default connect(() => {})(Alert)',
2121
'export default connect(null, null)(Alert)',
2222
'connect((state) => ({isActive: state.isActive}), null)(App)',
23+
'connect(null, null)(App)',
2324
`connect(
2425
(state) => {
2526
return {

0 commit comments

Comments
 (0)