From 73f135adb4d2c4fa02bffb037fc3df6909ca152c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Aaberg?= Date: Mon, 11 Dec 2017 22:06:04 +0100 Subject: [PATCH 1/2] Add more test cases for no-access-state-in-setstate --- .../lib/rules/no-access-state-in-setstate.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/lib/rules/no-access-state-in-setstate.js b/tests/lib/rules/no-access-state-in-setstate.js index 2ff75352d3..784c6f6ed7 100644 --- a/tests/lib/rules/no-access-state-in-setstate.js +++ b/tests/lib/rules/no-access-state-in-setstate.js @@ -64,6 +64,17 @@ ruleTester.run('no-access-state-in-setstate', rule, { }); `, parserOptions: parserOptions + }, { + code: [ + 'var Hello = React.createClass({', + ' onClick: function() {', + ' var nextValueNotUsed = this.state.value + 1', + ' var nextValue = 2', + ' this.setState({value: nextValue})', + ' }', + '});' + ].join('\n'), + parserOptions: parserOptions }], invalid: [{ @@ -103,6 +114,19 @@ 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() {', + ' var {state} = this', + ' this.setState({value: state.value + 1})', + ' }', + '});' + ].join('\n'), + parserOptions: parserOptions, + errors: [{ + message: 'Use callback in setState when referencing the previous state.' + }] }, { code: [ 'function nextState(state) {', From 495062336c85a189dbf7e351dfbf4eb3924384e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Aaberg?= Date: Mon, 11 Dec 2017 22:10:34 +0100 Subject: [PATCH 2/2] Make no-access-state-in-setstate find cases where state is destructured from this --- lib/rules/no-access-state-in-setstate.js | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/rules/no-access-state-in-setstate.js b/lib/rules/no-access-state-in-setstate.js index 975104d4a3..72e8081520 100644 --- a/lib/rules/no-access-state-in-setstate.js +++ b/lib/rules/no-access-state-in-setstate.js @@ -107,7 +107,8 @@ module.exports = { if (current.type === 'VariableDeclarator') { vars.push({ node: node, - scope: context.getScope() + scope: context.getScope(), + variableName: current.id.name }); break; } @@ -123,11 +124,14 @@ module.exports = { while (current.parent.type === 'BinaryExpression') { current = current.parent; } - if (current.parent.value === current) { + if ( + current.parent.value === current || + current.parent.object === current + ) { while (current.type !== 'Program') { if (isSetStateCall(current)) { vars - .filter(v => v.scope === context.getScope()) + .filter(v => v.scope === context.getScope() && v.variableName === node.name) .map(v => context.report( v.node, 'Use callback in setState when referencing the previous state.' @@ -136,6 +140,19 @@ module.exports = { current = current.parent; } } + }, + + ObjectPattern(node) { + const isDerivedFromThis = node.parent.init.type === 'ThisExpression'; + node.properties.forEach(property => { + if (property.key.name === 'state' && isDerivedFromThis) { + vars.push({ + node: property.key, + scope: context.getScope(), + variableName: property.key.name + }); + } + }); } }; }