diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ce65c9fb0..c0f09bb3f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange ### Fixed * prevent circular dependency in index and "all" config ([#3519][] @ljharb) +* [`destructuring-assignment`]: do not force destructuring of optionally chained properties ([#3520][] @ljharb) +[#3520]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3520 [#3519]: https://github.com/jsx-eslint/eslint-plugin-react/issues/3519 ## [7.32.0] - 2023.01.10 diff --git a/lib/rules/destructuring-assignment.js b/lib/rules/destructuring-assignment.js index 4678757c02..730828619e 100644 --- a/lib/rules/destructuring-assignment.js +++ b/lib/rules/destructuring-assignment.js @@ -137,7 +137,7 @@ module.exports = { || (contextName && node.object.name === contextName) ) && !isAssignmentLHS(node); - if (isPropUsed && configuration === 'always') { + if (isPropUsed && configuration === 'always' && !node.optional) { report(context, messages.useDestructAssignment, 'useDestructAssignment', { node, data: { @@ -149,7 +149,10 @@ module.exports = { // const foo = useContext(aContext); // foo.aProp const isContextUsed = contextSet.has(node.object.name) && !isAssignmentLHS(node); - if (isContextUsed && configuration === 'always') { + const optional = node.optional + // the below is for the old typescript-eslint parser + || context.getSourceCode().getText(node).slice(node.object.range[1] - node.range[0], node.object.range[1] - node.range[0] + 1) === '?'; + if (isContextUsed && configuration === 'always' && !optional) { report(context, messages.useDestructAssignment, 'useDestructAssignment', { node, data: { diff --git a/tests/lib/rules/destructuring-assignment.js b/tests/lib/rules/destructuring-assignment.js index 6c89907f29..b578fd0293 100644 --- a/tests/lib/rules/destructuring-assignment.js +++ b/tests/lib/rules/destructuring-assignment.js @@ -422,6 +422,17 @@ ruleTester.run('destructuring-assignment', rule, { options: ['never'], settings: { react: { version: '16.8.999' } }, }, + { + code: ` + import { useContext } from 'react'; + + const MyComponent = (props) => { + const foo = useContext(aContext); + return
{foo?.test}
+ }; + `, + features: ['optional chaining'], + }, ]), invalid: parsers.all([].concat(