diff --git a/lib/rules/no-access-state-in-setstate.js b/lib/rules/no-access-state-in-setstate.js index 8bbf3ba56d..53aeab11fe 100644 --- a/lib/rules/no-access-state-in-setstate.js +++ b/lib/rules/no-access-state-in-setstate.js @@ -6,6 +6,7 @@ 'use strict'; const docsUrl = require('../util/docsUrl'); +const Components = require('../util/Components'); // ------------------------------------------------------------------------------ // Rule Definition @@ -21,7 +22,7 @@ module.exports = { } }, - create(context) { + create: Components.detect((context, components, utils) => { function isSetStateCall(node) { return node.type === 'CallExpression' && node.callee.property @@ -39,6 +40,10 @@ module.exports = { return current.arguments[0] === node; } + function isClassComponent() { + return !!(utils.getParentES6Component() || utils.getParentES5Component()); + } + // 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 = []; @@ -46,6 +51,9 @@ module.exports = { const vars = []; return { CallExpression(node) { + if (!isClassComponent()) { + return; + } // Appends all the methods that are calling another // method containing this.state to the methods array methods.forEach((method) => { @@ -89,6 +97,7 @@ module.exports = { if ( node.property.name === 'state' && node.object.type === 'ThisExpression' + && isClassComponent() ) { let current = node; while (current.type !== 'Program') { @@ -170,5 +179,5 @@ module.exports = { }); } }; - } + }) }; diff --git a/tests/lib/rules/no-access-state-in-setstate.js b/tests/lib/rules/no-access-state-in-setstate.js index bd69bda4e6..b5e215b0e3 100644 --- a/tests/lib/rules/no-access-state-in-setstate.js +++ b/tests/lib/rules/no-access-state-in-setstate.js @@ -10,8 +10,8 @@ // ------------------------------------------------------------------------------ const RuleTester = require('eslint').RuleTester; -const rule = require('../../../lib/rules/no-access-state-in-setstate'); const parsers = require('../../helpers/parsers'); +const rule = require('../../../lib/rules/no-access-state-in-setstate'); const parserOptions = { ecmaVersion: 2018, @@ -20,11 +20,17 @@ const parserOptions = { } }; +const settings = { + react: { + createClass: 'createClass' + } +}; + // ------------------------------------------------------------------------------ // Tests // ------------------------------------------------------------------------------ -const ruleTester = new RuleTester(); +const ruleTester = new RuleTester({settings}); ruleTester.run('no-access-state-in-setstate', rule, { valid: [{ code: [ @@ -120,6 +126,17 @@ ruleTester.run('no-access-state-in-setstate', rule, { } `, parser: parsers.BABEL_ESLINT + }, { + code: ` + class Foo extends Abstract { + update = () => { + const result = this.getResult ( this.state.foo ); + return this.setState ({ result }); + }; + } + `, + parser: parsers.BABEL_ESLINT, + parserOptions }], invalid: [{ @@ -226,5 +243,17 @@ ruleTester.run('no-access-state-in-setstate', rule, { errors: [{ message: 'Use callback in setState when referencing the previous state.' }] + }, { + code: ` + class Hello extends React.Component { + onClick() { + this.setState(this.state, () => console.log(this.state)); + } + } + `, + parserOptions, + errors: [{ + message: 'Use callback in setState when referencing the previous state.' + }] }] });