diff --git a/CHANGELOG.md b/CHANGELOG.md index 60030fb736..5cdc1c22fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange * [`jsx-first-prop-new-line`]: ensure autofix preserves generics in component name ([#3546][] @ljharb) * [`no-unknown-property`]: allow `fill` prop on `` ([#3555][] @stefanprobst) * [`display-name`], [`prop-types`]: when checking for a capitalized name, ignore underscores entirely ([#3560][] @ljharb) +* [`no-unused-state`]: avoid crashing on a class field function with destructured state ([#3568][] @ljharb) +[#3568]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3568 [#3560]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3560 [#3555]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3555 [#3548]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3548 diff --git a/lib/rules/no-unused-state.js b/lib/rules/no-unused-state.js index 97a8eeeb2a..73a0e52163 100644 --- a/lib/rules/no-unused-state.js +++ b/lib/rules/no-unused-state.js @@ -379,14 +379,16 @@ module.exports = { } const argVar = scope.variables.find((x) => x.name === stateArg.name); - const stateRefs = argVar.references; + if (argVar) { + const stateRefs = argVar.references; - stateRefs.forEach((ref) => { - const identifier = ref.identifier; - if (identifier && identifier.parent && identifier.parent.type === 'MemberExpression') { - addUsedStateField(identifier.parent.property); - } - }); + stateRefs.forEach((ref) => { + const identifier = ref.identifier; + if (identifier && identifier.parent && identifier.parent.type === 'MemberExpression') { + addUsedStateField(identifier.parent.property); + } + }); + } }, 'PropertyDefinition:exit'(node) { diff --git a/tests/lib/rules/no-unused-state.js b/tests/lib/rules/no-unused-state.js index c37145a047..cf7d50a3cc 100644 --- a/tests/lib/rules/no-unused-state.js +++ b/tests/lib/rules/no-unused-state.js @@ -1095,6 +1095,21 @@ eslintTester.run('no-unused-state', rule, { parserOptions: { sourceType: 'module', }, + }, + { + code: ` + class Component extends React.Component { + static getDerivedStateFromProps = ({value, disableAnimation}: ToggleProps, {isControlled, isOn}: ToggleState) => { + return { isControlled, isOn }; + }; + + render() { + const { isControlled, isOn } = this.state; + return
{isControlled ? 'controlled' : ''}{isOn ? 'on' : ''}
; + } + } + `, + features: ['types', 'class fields'], } )),