diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3b729e25d9..e9b1baa3fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
* [`jsx-indent`]: Fix indent handling for closing parentheses ([#620][] @stefanbuck])
* [`prop-types`/`propTypes`]: follow a returned identifier to see if it is JSX ([#1046][] @ljharb)
* [`no-unused-state`]: TS: support `getDerivedStateFromProps` as an arrow function ([#2061][] @ljharb)
+* [`no-array-index-key`]: catch `.toString` and `String()` usage ([#2813][] @RedTn)
### Changed
* [readme] change [`jsx-runtime`] link from branch to sha ([#3160][] @tatsushitoji)
@@ -51,6 +52,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange
[#3160]: https://github.com/yannickcr/eslint-plugin-react/pull/3160
[#3133]: https://github.com/yannickcr/eslint-plugin-react/pull/3133
[#2921]: https://github.com/yannickcr/eslint-plugin-react/pull/2921
+[#2813]: https://github.com/yannickcr/eslint-plugin-react/pull/2813
[#2753]: https://github.com/yannickcr/eslint-plugin-react/pull/2753
[#2061]: https://github.com/yannickcr/eslint-plugin-react/issues/2061
[#1817]: https://github.com/yannickcr/eslint-plugin-react/issues/1817
diff --git a/lib/rules/no-array-index-key.js b/lib/rules/no-array-index-key.js
index 2e9f3db22c..27f75e9a41 100644
--- a/lib/rules/no-array-index-key.js
+++ b/lib/rules/no-array-index-key.js
@@ -159,6 +159,38 @@ module.exports = {
node,
});
});
+
+ return;
+ }
+
+ if (node.type === 'CallExpression'
+ && node.callee
+ && node.callee.type === 'MemberExpression'
+ && node.callee.object
+ && isArrayIndex(node.callee.object)
+ && node.callee.property
+ && node.callee.property.type === 'Identifier'
+ && node.callee.property.name === 'toString'
+ ) {
+ // key={bar.toString()}
+ report(context, messages.noArrayIndex, 'noArrayIndex', {
+ node,
+ });
+ return;
+ }
+
+ if (node.type === 'CallExpression'
+ && node.callee
+ && node.callee.type === 'Identifier'
+ && node.callee.name === 'String'
+ && Array.isArray(node.arguments)
+ && node.arguments.length > 0
+ && isArrayIndex(node.arguments[0])
+ ) {
+ // key={String(bar)}
+ report(context, messages.noArrayIndex, 'noArrayIndex', {
+ node: node.arguments[0],
+ });
}
}
diff --git a/tests/lib/rules/no-array-index-key.js b/tests/lib/rules/no-array-index-key.js
index c6317a1ff4..10de786f00 100644
--- a/tests/lib/rules/no-array-index-key.js
+++ b/tests/lib/rules/no-array-index-key.js
@@ -69,6 +69,21 @@ ruleTester.run('no-array-index-key', rule, {
{
code: 'foo.reduce((a, b) => a.concat(), [])',
},
+ {
+ code: 'foo.map((bar, i) => )',
+ },
+ {
+ code: 'foo.map((bar, i) => )',
+ },
+ {
+ code: 'foo.map((bar, i) => )',
+ },
+ {
+ code: 'foo.map((bar, i) => )',
+ },
+ {
+ code: 'foo.reduce((a, b) => a.concat(), [])',
+ },
{
code: 'foo.reduce((a, b, i) => a.concat(), [])',
},
@@ -251,6 +266,30 @@ ruleTester.run('no-array-index-key', rule, {
parserOptions: {
ecmaVersion: 2020,
},
+ },
+ {
+ code: `
+ foo.map((bar, index) => (
+
+ ))
+ `,
+ errors: [{ messageId: 'noArrayIndex' }],
+ },
+ {
+ code: `
+ foo.map((bar, index) => (
+
+ ))
+ `,
+ errors: [{ messageId: 'noArrayIndex' }],
+ },
+ {
+ code: `
+ foo.map((bar, index) => (
+
+ ))
+ `,
+ errors: [{ messageId: 'noArrayIndex' }],
}
)),
});