Skip to content

Commit 3194de2

Browse files
committed
Exclude references to this.state in setState callback
1 parent a908eb3 commit 3194de2

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
@@ -26,6 +26,16 @@ module.exports = {
2626
node.callee.object.type === 'ThisExpression';
2727
}
2828

29+
function isFirstArgumentInSetStateCall(current, node) {
30+
if (!isSetStateCall(current)) {
31+
return false;
32+
}
33+
while (node && node.parent !== current) {
34+
node = node.parent;
35+
}
36+
return current.arguments[0] === node;
37+
}
38+
2939
// The methods array contains all methods or functions that are using this.state
3040
// or that are calling another method or function using this.state
3141
const methods = [];
@@ -55,7 +65,7 @@ module.exports = {
5565
// to further check if they contains this.state
5666
let current = node.parent;
5767
while (current.type !== 'Program') {
58-
if (isSetStateCall(current)) {
68+
if (isFirstArgumentInSetStateCall(current, node)) {
5969
const methodName = node.callee.name;
6070
methods.map(method => {
6171
if (method.methodName === methodName) {
@@ -80,7 +90,7 @@ module.exports = {
8090
let current = node;
8191
while (current.type !== 'Program') {
8292
// Reporting if this.state is directly within this.setState
83-
if (isSetStateCall(current)) {
93+
if (isFirstArgumentInSetStateCall(current, node)) {
8494
context.report(
8595
node,
8696
'Use callback in setState when referencing the previous state.'
@@ -129,7 +139,7 @@ module.exports = {
129139
current.parent.object === current
130140
) {
131141
while (current.type !== 'Program') {
132-
if (isSetStateCall(current)) {
142+
if (isFirstArgumentInSetStateCall(current, node)) {
133143
vars
134144
.filter(v => v.scope === context.getScope() && v.variableName === node.name)
135145
.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
@@ -64,6 +64,25 @@ ruleTester.run('no-access-state-in-setstate', rule, {
6464
});
6565
`,
6666
parserOptions: parserOptions
67+
}, {
68+
// issue 1597: allow this.state in callback
69+
code: `
70+
var Hello = React.createClass({
71+
onClick: function() {
72+
this.setState({}, () => console.log(this.state));
73+
}
74+
});
75+
`,
76+
parserOptions: parserOptions
77+
}, {
78+
code: `
79+
var Hello = React.createClass({
80+
onClick: function() {
81+
this.setState({}, () => 1 + 1);
82+
}
83+
});
84+
`,
85+
parserOptions: parserOptions
6786
}, {
6887
code: [
6988
'var Hello = React.createClass({',
@@ -142,6 +161,30 @@ ruleTester.run('no-access-state-in-setstate', rule, {
142161
errors: [{
143162
message: 'Use callback in setState when referencing the previous state.'
144163
}]
164+
}, {
165+
code: `
166+
var Hello = React.createClass({
167+
onClick: function() {
168+
this.setState(this.state, () => 1 + 1);
169+
}
170+
});
171+
`,
172+
parserOptions: parserOptions,
173+
errors: [{
174+
message: 'Use callback in setState when referencing the previous state.'
175+
}]
176+
}, {
177+
code: `
178+
var Hello = React.createClass({
179+
onClick: function() {
180+
this.setState(this.state, () => console.log(this.state));
181+
}
182+
});
183+
`,
184+
parserOptions: parserOptions,
185+
errors: [{
186+
message: 'Use callback in setState when referencing the previous state.'
187+
}]
145188
}, {
146189
code: [
147190
'var Hello = React.createClass({',

0 commit comments

Comments
 (0)