diff --git a/CHANGELOG.md b/CHANGELOG.md
index 996905229e..88dab9ebfb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`jsx-no-leaked-render`]: Don't report errors on empty strings if React >= v18 ([#3488][] @himanshu007-creator)
* [`no-invalid-html-attribute`]: convert autofix to suggestion ([#3474][] @himanshu007-creator @ljharb)
* [`jsx-no-leaked-render`]: fix removing parentheses for conditionals ([#3502][] @akulsr0)
+* [`jsx-no-leaked-render`]: invalid fixes in coerce mode ([#3511][] @akulsr0)
### Changed
* [Docs] [`jsx-no-leaked-render`]: Remove mentions of empty strings for React 18 ([#3468][] @karlhorky)
@@ -28,6 +29,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [Docs] [`prefer-exact-props`]: fix example flow syntax ([#3510][] @smackfu)
* [Perf] use `anyOf` instead of `oneOf` (@ljharb @remcohaszing)
+[#3511]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3511
[#3510]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3510
[#3504]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3504
[#3499]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3499
diff --git a/lib/rules/jsx-no-leaked-render.js b/lib/rules/jsx-no-leaked-render.js
index dccba5b695..9ac795d98b 100644
--- a/lib/rules/jsx-no-leaked-render.js
+++ b/lib/rules/jsx-no-leaked-render.js
@@ -61,9 +61,21 @@ function ruleFixer(context, fixStrategy, fixer, reportedNode, leftNode, rightNod
if (isParenthesized(context, node)) {
nodeText = `(${nodeText})`;
}
+ if (node.parent && node.parent.type === 'ConditionalExpression' && node.parent.consequent.value === false) {
+ return `${getIsCoerceValidNestedLogicalExpression(node) ? '' : '!'}${nodeText}`;
+ }
return `${getIsCoerceValidNestedLogicalExpression(node) ? '' : '!!'}${nodeText}`;
}).join(' && ');
+ if (rightNode.parent.type === 'ConditionalExpression' && rightNode.parent.consequent.value === false) {
+ const consequentVal = rightNode.parent.consequent.raw || rightNode.parent.consequent.name;
+ const alternateVal = rightNode.parent.alternate.raw || rightNode.parent.alternate.name;
+ if (rightNode.parent.test.type === 'LogicalExpression') {
+ return fixer.replaceText(reportedNode, `${newText} ? ${consequentVal} : ${alternateVal}`);
+ }
+ return fixer.replaceText(reportedNode, `${newText} && ${rightNode.parent.alternate.name}`);
+ }
+
if (rightNode.type === 'ConditionalExpression') {
return fixer.replaceText(reportedNode, `${newText} && (${rightSideText})`);
}
diff --git a/tests/lib/rules/jsx-no-leaked-render.js b/tests/lib/rules/jsx-no-leaked-render.js
index cd9a1f982c..eb2b4b8045 100644
--- a/tests/lib/rules/jsx-no-leaked-render.js
+++ b/tests/lib/rules/jsx-no-leaked-render.js
@@ -847,5 +847,41 @@ ruleTester.run('jsx-no-leaked-render', rule, {
column: 24,
}],
},
+ {
+ code: `
+ const MyComponent = () => {
+ return
+ }
+ `,
+ output: `
+ const MyComponent = () => {
+ return
+ }
+ `,
+ options: [{validStrategies: ['coerce']}],
+ errors: [{
+ message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes',
+ line: 3,
+ column: 38,
+ }]
+ },
+ {
+ code: `
+ const MyComponent = () => {
+ return
+ }
+ `,
+ output: `
+ const MyComponent = () => {
+ return
+ }
+ `,
+ options: [{validStrategies: ['coerce']}],
+ errors: [{
+ message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes',
+ line: 3,
+ column: 38,
+ }]
+ },
]),
});