Skip to content

Commit

Permalink
Exclude references to this.state in setState callback
Browse files Browse the repository at this point in the history
  • Loading branch information
pfhayes committed Dec 15, 2017
1 parent a908eb3 commit 3194de2
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
16 changes: 13 additions & 3 deletions lib/rules/no-access-state-in-setstate.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ module.exports = {
node.callee.object.type === 'ThisExpression';
}

function isFirstArgumentInSetStateCall(current, node) {
if (!isSetStateCall(current)) {
return false;
}
while (node && node.parent !== current) {
node = node.parent;
}
return current.arguments[0] === node;
}

// The methods array contains all methods or functions that are using this.state
// or that are calling another method or function using this.state
const methods = [];
Expand Down Expand Up @@ -55,7 +65,7 @@ module.exports = {
// to further check if they contains this.state
let current = node.parent;
while (current.type !== 'Program') {
if (isSetStateCall(current)) {
if (isFirstArgumentInSetStateCall(current, node)) {
const methodName = node.callee.name;
methods.map(method => {
if (method.methodName === methodName) {
Expand All @@ -80,7 +90,7 @@ module.exports = {
let current = node;
while (current.type !== 'Program') {
// Reporting if this.state is directly within this.setState
if (isSetStateCall(current)) {
if (isFirstArgumentInSetStateCall(current, node)) {
context.report(
node,
'Use callback in setState when referencing the previous state.'
Expand Down Expand Up @@ -129,7 +139,7 @@ module.exports = {
current.parent.object === current
) {
while (current.type !== 'Program') {
if (isSetStateCall(current)) {
if (isFirstArgumentInSetStateCall(current, node)) {
vars
.filter(v => v.scope === context.getScope() && v.variableName === node.name)
.map(v => context.report(
Expand Down
43 changes: 43 additions & 0 deletions tests/lib/rules/no-access-state-in-setstate.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,25 @@ ruleTester.run('no-access-state-in-setstate', rule, {
});
`,
parserOptions: parserOptions
}, {
// issue 1597: allow this.state in callback
code: `
var Hello = React.createClass({
onClick: function() {
this.setState({}, () => console.log(this.state));
}
});
`,
parserOptions: parserOptions
}, {
code: `
var Hello = React.createClass({
onClick: function() {
this.setState({}, () => 1 + 1);
}
});
`,
parserOptions: parserOptions
}, {
code: [
'var Hello = React.createClass({',
Expand Down Expand Up @@ -142,6 +161,30 @@ ruleTester.run('no-access-state-in-setstate', rule, {
errors: [{
message: 'Use callback in setState when referencing the previous state.'
}]
}, {
code: `
var Hello = React.createClass({
onClick: function() {
this.setState(this.state, () => 1 + 1);
}
});
`,
parserOptions: parserOptions,
errors: [{
message: 'Use callback in setState when referencing the previous state.'
}]
}, {
code: `
var Hello = React.createClass({
onClick: function() {
this.setState(this.state, () => console.log(this.state));
}
});
`,
parserOptions: parserOptions,
errors: [{
message: 'Use callback in setState when referencing the previous state.'
}]
}, {
code: [
'var Hello = React.createClass({',
Expand Down

0 comments on commit 3194de2

Please sign in to comment.