From 3194de2fdb24d8aa7f858a62cf95b36172a75b88 Mon Sep 17 00:00:00 2001 From: Patrick Hayes Date: Fri, 15 Dec 2017 15:40:06 -0800 Subject: [PATCH 1/2] Exclude references to this.state in setState callback --- lib/rules/no-access-state-in-setstate.js | 16 +++++-- .../lib/rules/no-access-state-in-setstate.js | 43 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/lib/rules/no-access-state-in-setstate.js b/lib/rules/no-access-state-in-setstate.js index 72e8081520..de640cfc28 100644 --- a/lib/rules/no-access-state-in-setstate.js +++ b/lib/rules/no-access-state-in-setstate.js @@ -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 = []; @@ -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) { @@ -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.' @@ -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( diff --git a/tests/lib/rules/no-access-state-in-setstate.js b/tests/lib/rules/no-access-state-in-setstate.js index 784c6f6ed7..bcc3bba06d 100644 --- a/tests/lib/rules/no-access-state-in-setstate.js +++ b/tests/lib/rules/no-access-state-in-setstate.js @@ -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({', @@ -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({', From af6cb319a578b78c21b8e5a03f6a80c6d1d41961 Mon Sep 17 00:00:00 2001 From: Patrick Hayes Date: Fri, 15 Dec 2017 15:42:07 -0800 Subject: [PATCH 2/2] Fix typo in comment --- tests/lib/rules/no-access-state-in-setstate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/rules/no-access-state-in-setstate.js b/tests/lib/rules/no-access-state-in-setstate.js index bcc3bba06d..a77e420b8d 100644 --- a/tests/lib/rules/no-access-state-in-setstate.js +++ b/tests/lib/rules/no-access-state-in-setstate.js @@ -65,7 +65,7 @@ ruleTester.run('no-access-state-in-setstate', rule, { `, parserOptions: parserOptions }, { - // issue 1597: allow this.state in callback + // issue 1604: allow this.state in callback code: ` var Hello = React.createClass({ onClick: function() {