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' }], } )), });