Skip to content

Commit 60d15da

Browse files
committed
[Fix]: detect missing keys in return statement with ternary operator
Fix #3925
1 parent dd2e968 commit 60d15da

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

lib/rules/jsx-key.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,20 @@ module.exports = {
146146
getReturnStatements(node.body)
147147
.filter((returnStatement) => returnStatement && returnStatement.argument)
148148
.forEach((returnStatement) => {
149-
checkIteratorElement(returnStatement.argument);
149+
const argument = returnStatement.argument;
150+
151+
if (argument.type === 'ConditionalExpression') {
152+
const shouldCheckNode = (n) => n && (n.type === 'JSXElement' || n.type === 'JSXFragment');
153+
154+
if (shouldCheckNode(argument.consequent)) {
155+
checkIteratorElement(argument.consequent);
156+
}
157+
if (shouldCheckNode(argument.alternate)) {
158+
checkIteratorElement(argument.alternate);
159+
}
160+
} else {
161+
checkIteratorElement(argument);
162+
}
150163
});
151164
}
152165
}

tests/lib/rules/jsx-key.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ const settings = {
3636
const ruleTester = new RuleTester({ parserOptions });
3737
ruleTester.run('jsx-key', rule, {
3838
valid: parsers.all([
39+
{
40+
code: `
41+
[1, 2, 3].map((item) => {
42+
return item === 'bar' ? <div key={item}>{item}</div> : <span key={item}>{item}</span>;
43+
})`,
44+
},
3945
{ code: 'fn()' },
4046
{ code: '[1, 2, 3].map(function () {})' },
4147
{ code: '<App />;' },
@@ -207,6 +213,57 @@ ruleTester.run('jsx-key', rule, {
207213
},
208214
]),
209215
invalid: parsers.all([
216+
{
217+
code: `
218+
[1, 2, 3].map((item) => {
219+
return item === 'bar' ? <div>{item}</div> : <span>{item}</span>;
220+
})`,
221+
errors: [
222+
{ messageId: 'missingIterKey' },
223+
{ messageId: 'missingIterKey' },
224+
],
225+
},
226+
{
227+
code: `
228+
[1, 2, 3].map(function(item) {
229+
return item === 'bar' ? <div>{item}</div> : <span>{item}</span>;
230+
})`,
231+
errors: [
232+
{ messageId: 'missingIterKey' },
233+
{ messageId: 'missingIterKey' },
234+
],
235+
},
236+
{
237+
code: `
238+
Array.from([1, 2, 3], (item) => {
239+
return item === 'bar' ? <div>{item}</div> : <span>{item}</span>;
240+
})`,
241+
errors: [
242+
{ messageId: 'missingIterKey' },
243+
{ messageId: 'missingIterKey' },
244+
],
245+
},
246+
{
247+
code: `
248+
import { Fragment } from 'react';
249+
250+
const ITEMS = ['bar', 'foo'];
251+
252+
export default function BugIssue() {
253+
return (
254+
<Fragment>
255+
{ITEMS.map((item) => {
256+
return item === 'bar' ? <div>{item}</div> : <span>{item}</span>;
257+
})}
258+
</Fragment>
259+
);
260+
}
261+
`,
262+
errors: [
263+
{ messageId: 'missingIterKey' },
264+
{ messageId: 'missingIterKey' },
265+
],
266+
},
210267
{
211268
code: '[<App />];',
212269
errors: [{ messageId: 'missingArrayKey' }],

0 commit comments

Comments
 (0)