diff --git a/lib/rules/no-unused-state.js b/lib/rules/no-unused-state.js index d4bef8c278..4040d80dc7 100644 --- a/lib/rules/no-unused-state.js +++ b/lib/rules/no-unused-state.js @@ -237,6 +237,27 @@ module.exports = { ) { addStateFields(node.value); } + + if ( + !node.static && + node.value && + node.value.type === 'ArrowFunctionExpression' + ) { + // Create a new set for this.state aliases local to this method. + classInfo.aliases = new Set(); + } + }, + + 'ClassProperty:exit'(node) { + if ( + classInfo && + !node.static && + node.value && + node.value.type === 'ArrowFunctionExpression' + ) { + // Forget our set of local aliases. + classInfo.aliases = null; + } }, MethodDefinition() { diff --git a/tests/lib/rules/no-unused-state.js b/tests/lib/rules/no-unused-state.js index 4fbb8a4f22..62f9599e4c 100644 --- a/tests/lib/rules/no-unused-state.js +++ b/tests/lib/rules/no-unused-state.js @@ -387,6 +387,22 @@ eslintTester.run('no-unused-state', rule, { return ; } }`, + `class NonRenderClassMethodFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0, bar: 0 }; + } + doSomething() { + const { foo } = this.state; + return this.state.foo; + } + doSomethingElse() { + const { state: { bar }} = this; + return bar; + } + render() { + return ; + } + }`, { code: `class TypeCastExpressionSpreadFalseNegativeTest extends React.Component { constructor() { @@ -397,6 +413,72 @@ eslintTester.run('no-unused-state', rule, { } }`, parser: 'babel-eslint' + }, + { + code: `class ArrowFunctionClassMethodDestructuringFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + + doSomething = () => { + const { state: { foo } } = this; + + return foo; + } + + render() { + return ; + } + }`, + parser: 'babel-eslint' + }, + { + code: `class ArrowFunctionClassMethodWithClassPropertyTransformFalseNegativeTest extends React.Component { + state = { foo: 0 }; + + doSomething = () => { + const { state:{ foo } } = this; + + return foo; + } + + render() { + return ; + } + }`, + parser: 'babel-eslint' + }, + { + code: `class ArrowFunctionClassMethodDeepDestructuringFalseNegativeTest extends React.Component { + state = { foo: { bar: 0 } }; + + doSomething = () => { + const { state: { foo: { bar }}} = this; + + return bar; + } + + render() { + return ; + } + }`, + parser: 'babel-eslint' + }, + { + code: `class ArrowFunctionClassMethodDestructuringAssignmentFalseNegativeTest extends React.Component { + state = { foo: 0 }; + + doSomething = () => { + const { state: { foo: bar }} = this; + + return bar; + } + + render() { + return ; + } + }`, + parser: 'babel-eslint' } ], @@ -642,6 +724,21 @@ eslintTester.run('no-unused-state', rule, { }`, errors: getErrorMessages(['foo']) }, + { + code: `class UnusedStateArrowFunctionMethodTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + doSomething = () => { + return null; + } + render() { + return ; + } + }`, + errors: getErrorMessages(['foo']), + parser: 'babel-eslint' + }, { code: `class TypeCastExpressionTest extends React.Component { constructor() {