Skip to content

Commit 70e8a02

Browse files
authored
Merge pull request #1610 from pfhayes/setstate
Exclude references to this.state in setState callback
2 parents 7443a37 + af6cb31 commit 70e8a02

File tree

2 files changed

+56
-3
lines changed

2 files changed

+56
-3
lines changed

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ module.exports = {
2929
node.callee.object.type === 'ThisExpression';
3030
}
3131

32+
function isFirstArgumentInSetStateCall(current, node) {
33+
if (!isSetStateCall(current)) {
34+
return false;
35+
}
36+
while (node && node.parent !== current) {
37+
node = node.parent;
38+
}
39+
return current.arguments[0] === node;
40+
}
41+
3242
// The methods array contains all methods or functions that are using this.state
3343
// or that are calling another method or function using this.state
3444
const methods = [];
@@ -58,7 +68,7 @@ module.exports = {
5868
// to further check if they contains this.state
5969
let current = node.parent;
6070
while (current.type !== 'Program') {
61-
if (isSetStateCall(current)) {
71+
if (isFirstArgumentInSetStateCall(current, node)) {
6272
const methodName = node.callee.name;
6373
methods.map(method => {
6474
if (method.methodName === methodName) {
@@ -83,7 +93,7 @@ module.exports = {
8393
let current = node;
8494
while (current.type !== 'Program') {
8595
// Reporting if this.state is directly within this.setState
86-
if (isSetStateCall(current)) {
96+
if (isFirstArgumentInSetStateCall(current, node)) {
8797
context.report(
8898
node,
8999
'Use callback in setState when referencing the previous state.'
@@ -132,7 +142,7 @@ module.exports = {
132142
current.parent.object === current
133143
) {
134144
while (current.type !== 'Program') {
135-
if (isSetStateCall(current)) {
145+
if (isFirstArgumentInSetStateCall(current, node)) {
136146
vars
137147
.filter(v => v.scope === context.getScope() && v.variableName === node.name)
138148
.map(v => context.report(

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,25 @@ ruleTester.run('no-access-state-in-setstate', rule, {
6565
});
6666
`,
6767
parserOptions: parserOptions
68+
}, {
69+
// issue 1604: allow this.state in callback
70+
code: `
71+
var Hello = React.createClass({
72+
onClick: function() {
73+
this.setState({}, () => console.log(this.state));
74+
}
75+
});
76+
`,
77+
parserOptions: parserOptions
78+
}, {
79+
code: `
80+
var Hello = React.createClass({
81+
onClick: function() {
82+
this.setState({}, () => 1 + 1);
83+
}
84+
});
85+
`,
86+
parserOptions: parserOptions
6887
}, {
6988
code: [
7089
'var Hello = React.createClass({',
@@ -150,6 +169,30 @@ ruleTester.run('no-access-state-in-setstate', rule, {
150169
errors: [{
151170
message: 'Use callback in setState when referencing the previous state.'
152171
}]
172+
}, {
173+
code: `
174+
var Hello = React.createClass({
175+
onClick: function() {
176+
this.setState(this.state, () => 1 + 1);
177+
}
178+
});
179+
`,
180+
parserOptions: parserOptions,
181+
errors: [{
182+
message: 'Use callback in setState when referencing the previous state.'
183+
}]
184+
}, {
185+
code: `
186+
var Hello = React.createClass({
187+
onClick: function() {
188+
this.setState(this.state, () => console.log(this.state));
189+
}
190+
});
191+
`,
192+
parserOptions: parserOptions,
193+
errors: [{
194+
message: 'Use callback in setState when referencing the previous state.'
195+
}]
153196
}, {
154197
code: [
155198
'var Hello = React.createClass({',

0 commit comments

Comments
 (0)