Skip to content

Commit e518d11

Browse files
committed
check for .map in chain expression
1 parent 6aa8acb commit e518d11

File tree

2 files changed

+39
-22
lines changed

2 files changed

+39
-22
lines changed

docs/prefer-for.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ function Component(props) {
6565
);
6666
}
6767

68+
function Component(props) {
69+
return (
70+
<ol>
71+
{props.data?.map((d) => (
72+
<li>{d.text}</li>
73+
))}
74+
</ol>
75+
);
76+
}
77+
// after eslint --fix:
78+
function Component(props) {
79+
return <ol>{<For each={props.data}>{(d) => <li>{d.text}</li>}</For>}</ol>;
80+
}
81+
6882
let Component = (props) => (
6983
<ol>
7084
{props.data.map(() => (

src/rules/prefer-for.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -48,29 +48,32 @@ const rule: TSESLint.RuleModule<"preferFor" | "preferForOrIndex", []> = {
4848
});
4949
};
5050

51-
return {
52-
"JSXElement > JSXExpressionContainer > CallExpression": (node: T.CallExpression) => {
53-
if (
54-
node.callee.type === "MemberExpression" &&
55-
getPropertyName(node.callee) === "map" &&
56-
node.arguments.length === 1 && // passing thisArg to Array.prototype.map is rare, deopt in that case
57-
isFunctionNode(node.arguments[0])
58-
) {
59-
const mapFnNode = node.arguments[0];
60-
if (mapFnNode.params.length === 1 && mapFnNode.params[0].type !== "RestElement") {
61-
// The map fn doesn't take an index param, so it can't possibly be an index-keyed list. Use <For />.
62-
// The returned JSX, if it's coming from React, will have an unnecessary `key` prop to be removed in
63-
// the useless-keys rule.
64-
reportPreferFor(node);
65-
} else {
66-
// Too many possible solutions to make a suggestion or fix
67-
context.report({
68-
node,
69-
messageId: "preferForOrIndex",
70-
});
71-
}
51+
const report = (node: T.CallExpression) => {
52+
if (
53+
node.callee.type === "MemberExpression" &&
54+
getPropertyName(node.callee) === "map" &&
55+
node.arguments.length === 1 && // passing thisArg to Array.prototype.map is rare, deopt in that case
56+
isFunctionNode(node.arguments[0])
57+
) {
58+
const mapFnNode = node.arguments[0];
59+
if (mapFnNode.params.length === 1 && mapFnNode.params[0].type !== "RestElement") {
60+
// The map fn doesn't take an index param, so it can't possibly be an index-keyed list. Use <For />.
61+
// The returned JSX, if it's coming from React, will have an unnecessary `key` prop to be removed in
62+
// the useless-keys rule.
63+
reportPreferFor(node);
64+
} else {
65+
// Too many possible solutions to make a suggestion or fix
66+
context.report({
67+
node,
68+
messageId: "preferForOrIndex",
69+
});
7270
}
73-
},
71+
}
72+
};
73+
74+
return {
75+
"JSXElement > JSXExpressionContainer > CallExpression": report,
76+
"JSXElement > JSXExpressionContainer > ChainExpression > CallExpression": report,
7477
};
7578
},
7679
};

0 commit comments

Comments
 (0)