Skip to content

Commit a746361

Browse files
fix: proper implementation of mapDispatchToProps-prefer-object (#7)
1 parent 31b6099 commit a746361

File tree

5 files changed

+111
-26
lines changed

5 files changed

+111
-26
lines changed

docs/rules/mapDispatchToProps-prefer-object.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,24 @@ In most cases one just needs to pass an object with an actions. And connect wrap
1010
The following pattern is considered incorrect:
1111

1212
```js
13-
const mapDispatchToProps = (dispatch) => (
14-
{
15-
requestFilteredItems: (keyword) => {
16-
dispatch(requestFilteredItems(keyword));
17-
}
18-
}
19-
)
13+
const mapDispatchToProps = (dispatch) => dispatch(action())
2014
```
2115

22-
The following patterns are considered correct:
16+
```js
17+
connect((state) => state, (dispatch) => dispatch(action()))(App)
18+
```
2319

2420
```js
2521
const mapDispatchToProps = () => {}
2622
```
2723

24+
The following patterns are considered correct:
25+
26+
2827
```js
2928
const mapDispatchToProps = {anAction: anAction}
3029
```
30+
31+
```js
32+
connect((state) => state, {anAction}))(App)
33+
```
Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,41 @@
1+
const isReactReduxConnect = require('../isReactReduxConnect');
2+
13
const report = function (context, node) {
24
context.report({
35
message: 'mapDispatchToProps should return object',
46
node,
57
});
68
};
79

8-
const checkDeclaration = function (context, node) {
9-
const init = (
10-
node.id &&
11-
node.id.name === 'mapDispatchToProps' &&
12-
((node.init && node.init.body) || node.body)
13-
);
14-
if (init && context.getSource(init) !== '{}') {
15-
report(context, node);
16-
}
17-
};
1810

1911
module.exports = function (context) {
2012
return {
2113
VariableDeclaration(node) {
22-
node.declarations.forEach(decl => checkDeclaration(context, decl));
14+
node.declarations.forEach((decl) => {
15+
if (decl.id && decl.id.name === 'mapDispatchToProps') {
16+
if (decl.init && (
17+
decl.init.type === 'ArrowFunctionExpression' ||
18+
decl.init.type === 'FunctionExpression'
19+
)) {
20+
report(context, decl);
21+
}
22+
}
23+
});
2324
},
2425
FunctionDeclaration(node) {
25-
checkDeclaration(context, node);
26+
if (node.id && node.id.name === 'mapDispatchToProps') {
27+
report(context, node.body);
28+
}
29+
},
30+
CallExpression(node) {
31+
if (isReactReduxConnect(node)) {
32+
const mapDispatchToProps = node.arguments && node.arguments[1];
33+
if (mapDispatchToProps.type === 'ArrowFunctionExpression' ||
34+
mapDispatchToProps.type === 'FunctionExpression'
35+
) {
36+
report(context, mapDispatchToProps);
37+
}
38+
}
2639
},
2740
};
2841
};

lib/rules/mapStateToProps-no-store.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ module.exports = function (context) {
3131
node.declarations.forEach((decl) => {
3232
if (decl.id && decl.id.name === 'mapStateToProps') {
3333
const body = decl.init.body;
34-
const firxtParamName = decl.init.params &&
34+
const firstParamName = decl.init.params &&
3535
decl.init.params[0] &&
3636
decl.init.params[0].name;
37-
checkFunction(context, body, firxtParamName);
37+
checkFunction(context, body, firstParamName);
3838
}
3939
});
4040
},

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/mapStateToProps-no-store",
17-
"debug-test": "mocha --debug-brk --inspect tests/lib/rules/mapStateToProps-no-store",
16+
"test-single": "mocha tests/lib/rules/mapDispatchToProps-prefer-object",
17+
"debug-test": "mocha --debug-brk --inspect tests/lib/rules/mapDispatchToProps-prefer-object",
1818
"semantic-release": "semantic-release",
1919
"commitmsg": "npm run test && commitlint -e $GIT_PARAMS"
2020
},

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

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,29 @@ const ruleTester = new RuleTester({ parserOptions });
1616
ruleTester.run('mapDispatchToProps-prefer-object', rule, {
1717
valid: [
1818
'const mapDispatchToProps = {anAction: anAction}',
19-
'const mapDispatchToProps = () => {}',
20-
'function mapDispatchToProps () {}',
19+
`export default connect(
20+
state => ({
21+
productsList: state.Products.productsList,
22+
}),
23+
{ fetchProducts }
24+
)(Products);
25+
`,
2126
],
2227
invalid: [{
28+
code: 'function mapDispatchToProps () {}',
29+
errors: [
30+
{
31+
message: 'mapDispatchToProps should return object',
32+
},
33+
],
34+
}, {
35+
code: 'const mapDispatchToProps = () => {}',
36+
errors: [
37+
{
38+
message: 'mapDispatchToProps should return object',
39+
},
40+
],
41+
}, {
2342
code: `const mapDispatchToProps = (dispatch) => (
2443
{
2544
requestFilteredItems: (client, keyword) => {
@@ -32,5 +51,55 @@ ruleTester.run('mapDispatchToProps-prefer-object', rule, {
3251
message: 'mapDispatchToProps should return object',
3352
},
3453
],
54+
}, {
55+
code: `function mapDispatchToProps(dispatch) {
56+
return { requestFilteredItems: (client, keyword) => {
57+
dispatch(requestFilteredItems(client, keyword));
58+
}
59+
}
60+
}`,
61+
errors: [
62+
{
63+
message: 'mapDispatchToProps should return object',
64+
},
65+
],
66+
}, {
67+
code: `const mapDispatchToProps = function(dispatch) {
68+
return { requestFilteredItems: (client, keyword) => {
69+
dispatch(requestFilteredItems(client, keyword));
70+
}
71+
}
72+
}`,
73+
errors: [
74+
{
75+
message: 'mapDispatchToProps should return object',
76+
},
77+
],
78+
}, {
79+
code: `export default connect(
80+
state => ({
81+
productsList: state.Products.productsList,
82+
}),
83+
dispatch => dispatch(action())
84+
)(Products);
85+
`,
86+
errors: [
87+
{
88+
message: 'mapDispatchToProps should return object',
89+
},
90+
],
91+
}, {
92+
code: `export default connect(
93+
state => ({
94+
productsList: state.Products.productsList,
95+
}),
96+
function(dispatch){ return dispatch(action()) }
97+
)(Products);
98+
`,
99+
errors: [
100+
{
101+
message: 'mapDispatchToProps should return object',
102+
},
103+
],
35104
}],
36105
});

0 commit comments

Comments
 (0)