Skip to content

Commit 7227571

Browse files
jzabalaljharb
authored andcommitted
[Fix] no-access-state-in-setstate: add check for class component
Fixes #2464.
1 parent 8466625 commit 7227571

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

lib/rules/no-access-state-in-setstate.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
'use strict';
77

88
const docsUrl = require('../util/docsUrl');
9+
const Components = require('../util/Components');
910

1011
// ------------------------------------------------------------------------------
1112
// Rule Definition
@@ -21,7 +22,7 @@ module.exports = {
2122
}
2223
},
2324

24-
create(context) {
25+
create: Components.detect((context, components, utils) => {
2526
function isSetStateCall(node) {
2627
return node.type === 'CallExpression'
2728
&& node.callee.property
@@ -39,13 +40,20 @@ module.exports = {
3940
return current.arguments[0] === node;
4041
}
4142

43+
function isClassComponent() {
44+
return !!(utils.getParentES6Component() || utils.getParentES5Component());
45+
}
46+
4247
// The methods array contains all methods or functions that are using this.state
4348
// or that are calling another method or function using this.state
4449
const methods = [];
4550
// The vars array contains all variables that contains this.state
4651
const vars = [];
4752
return {
4853
CallExpression(node) {
54+
if (!isClassComponent()) {
55+
return;
56+
}
4957
// Appends all the methods that are calling another
5058
// method containing this.state to the methods array
5159
methods.forEach((method) => {
@@ -89,6 +97,7 @@ module.exports = {
8997
if (
9098
node.property.name === 'state'
9199
&& node.object.type === 'ThisExpression'
100+
&& isClassComponent()
92101
) {
93102
let current = node;
94103
while (current.type !== 'Program') {
@@ -170,5 +179,5 @@ module.exports = {
170179
});
171180
}
172181
};
173-
}
182+
})
174183
};

tests/lib/rules/no-access-state-in-setstate.js

+31-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
// ------------------------------------------------------------------------------
1111

1212
const RuleTester = require('eslint').RuleTester;
13-
const rule = require('../../../lib/rules/no-access-state-in-setstate');
1413
const parsers = require('../../helpers/parsers');
14+
const rule = require('../../../lib/rules/no-access-state-in-setstate');
1515

1616
const parserOptions = {
1717
ecmaVersion: 2018,
@@ -20,11 +20,17 @@ const parserOptions = {
2020
}
2121
};
2222

23+
const settings = {
24+
react: {
25+
createClass: 'createClass'
26+
}
27+
};
28+
2329
// ------------------------------------------------------------------------------
2430
// Tests
2531
// ------------------------------------------------------------------------------
2632

27-
const ruleTester = new RuleTester();
33+
const ruleTester = new RuleTester({settings});
2834
ruleTester.run('no-access-state-in-setstate', rule, {
2935
valid: [{
3036
code: [
@@ -120,6 +126,17 @@ ruleTester.run('no-access-state-in-setstate', rule, {
120126
}
121127
`,
122128
parser: parsers.BABEL_ESLINT
129+
}, {
130+
code: `
131+
class Foo extends Abstract {
132+
update = () => {
133+
const result = this.getResult ( this.state.foo );
134+
return this.setState ({ result });
135+
};
136+
}
137+
`,
138+
parser: parsers.BABEL_ESLINT,
139+
parserOptions
123140
}],
124141

125142
invalid: [{
@@ -226,5 +243,17 @@ ruleTester.run('no-access-state-in-setstate', rule, {
226243
errors: [{
227244
message: 'Use callback in setState when referencing the previous state.'
228245
}]
246+
}, {
247+
code: `
248+
class Hello extends React.Component {
249+
onClick() {
250+
this.setState(this.state, () => console.log(this.state));
251+
}
252+
}
253+
`,
254+
parserOptions,
255+
errors: [{
256+
message: 'Use callback in setState when referencing the previous state.'
257+
}]
229258
}]
230259
});

0 commit comments

Comments
 (0)