Skip to content

Commit d97e3ed

Browse files
akulsr0ljharb
authored andcommitted
[Fix] jsx-no-leaked-render: invalid report if left side is boolean
1 parent 03cd4b5 commit d97e3ed

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
77

88
### Fixed
99
* [`boolean-prop-naming`]: avoid a crash with a non-TSTypeReference type ([#3718][] @developer-bandi)
10+
* [`jsx-no-leaked-render`]: invalid report if left side is boolean ([#3746][] @akulsr0)
1011

12+
[#3746]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3746
1113
[#3718]: https://github.com/jsx-eslint/eslint-plugin-react/pull/3718
1214

1315
## [7.34.1] - 2024.03.15

lib/rules/jsx-no-leaked-render.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const from = require('es-iterator-helpers/Iterator.from');
1010

1111
const docsUrl = require('../util/docsUrl');
1212
const report = require('../util/report');
13+
const variableUtil = require('../util/variable');
1314
const testReactVersion = require('../util/version').testReactVersion;
1415
const isParenthesized = require('../util/ast').isParenthesized;
1516

@@ -160,6 +161,17 @@ module.exports = {
160161
if (isCoerceValidLeftSide || getIsCoerceValidNestedLogicalExpression(leftSide)) {
161162
return;
162163
}
164+
const variables = variableUtil.variablesInScope(context);
165+
const leftSideVar = variableUtil.getVariable(variables, leftSide.name);
166+
if (leftSideVar) {
167+
const leftSideValue = leftSideVar.defs
168+
&& leftSideVar.defs.length
169+
&& leftSideVar.defs[0].node.init
170+
&& leftSideVar.defs[0].node.init.value;
171+
if (typeof leftSideValue === 'boolean') {
172+
return;
173+
}
174+
}
163175
}
164176

165177
if (testReactVersion(context, '>= 18') && leftSide.type === 'Literal' && leftSide.value === '') {

tests/lib/rules/jsx-no-leaked-render.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,24 @@ ruleTester.run('jsx-no-leaked-render', rule, {
195195
`,
196196
options: [{ validStrategies: ['coerce'] }],
197197
},
198+
{
199+
code: `
200+
const isOpen = true;
201+
const Component = () => {
202+
return <Popover open={isOpen && items.length > 0} />
203+
}
204+
`,
205+
options: [{ validStrategies: ['coerce'] }],
206+
},
207+
{
208+
code: `
209+
const isOpen = false;
210+
const Component = () => {
211+
return <Popover open={isOpen && items.length > 0} />
212+
}
213+
`,
214+
options: [{ validStrategies: ['coerce'] }],
215+
},
198216
]) || [],
199217

200218
invalid: parsers.all([].concat(
@@ -972,6 +990,26 @@ ruleTester.run('jsx-no-leaked-render', rule, {
972990
line: 5,
973991
column: 16,
974992
}],
975-
} : []
993+
} : [],
994+
{
995+
code: `
996+
const isOpen = 0;
997+
const Component = () => {
998+
return <Popover open={isOpen && items.length > 0} />
999+
}
1000+
`,
1001+
output: `
1002+
const isOpen = 0;
1003+
const Component = () => {
1004+
return <Popover open={!!isOpen && items.length > 0} />
1005+
}
1006+
`,
1007+
options: [{ validStrategies: ['coerce'] }],
1008+
errors: [{
1009+
message: 'Potential leaked value that might cause unintentionally rendered values or rendering crashes',
1010+
line: 4,
1011+
column: 33,
1012+
}],
1013+
}
9761014
)),
9771015
});

0 commit comments

Comments
 (0)