no-array-index-key

Try in Playground
react-best-practicesBest PracticeWarning

0

No tags

No CWE or CVE

Warns if an element uses an Array index as its key.

The key is used by React to identify which items were added, removed, or updated. This allows React to determine which elements can remain stable between renders.

Using an array index as a key isn't recommended because React can't uniquely identify your elements or components, which can lead to unnecessary renders.

Example:

  • You are using an array index as your key for a list of components and you remove a component near the middle of your list.
  • All of your components after that removed element will be re-rendered because their key value has changed.

Solution:

  • By using a unique identifier for your components like an id or a name you can save yourself and your application from these unnecessary re-renders.

Ast Rule: html element


no-array-index-key

How to write a rule
function visit(node) {
  if (!node || !node.attributes || node.attributes === 0) return;

  // check if the node has a "key" attribute
  const keyAttribute = node.attributes.find((a) => a.name?.value === "key");
  if (!keyAttribute) return;

  // check the value passed in the attribute
  const keyAttributeValue = keyAttribute?.value?.elements[0].value;
  if (!keyAttributeValue) return;

  const currentFunctionCall = node.context.currentFunctionCall;
  if (!currentFunctionCall) return;

  // check if we're in a map function
  if (!currentFunctionCall.functionName?.name?.value === "map") return;

  // check that we get the arguments of the map function
  if (currentFunctionCall?.arguments?.values?.length !== 1) return;

  const arg = currentFunctionCall.arguments.values[0].value;
  if (arg.astType !== "functionexpression") return;

  // check if the function is using the second parameter - index
  if (arg.parameters?.values.length < 2) return;

  const indexName = arg.parameters.values[1].name.value;

  // if the second argument of map is the same value as the key property, raise an issue
  if (indexName === keyAttributeValue) {
    const error = buildError(
      keyAttribute.start.line,
      keyAttribute.start.col,
      keyAttribute.end.line,
      keyAttribute.end.col,
      "Don't use the array index as key",
      "WARNING",
      "BEST_PRACTICE"
    );
    addError(error);
  }
}

correct-code.jsx

Expected test result: no error

things.forEach((thing) => (
  <Hello key={thing.id} />
));

things.forEach((thing, index) => (
  <Hello key={thing.id} />
));

things.forEach((thing, index, arr) => (
  <Hello key={arr[index].id} />
));

incorrect-code.jsx

Expected test result: has error

things.map((thing, i) => (
  <Hello key={i} />
));

things.map((thing, idx) => (
  <Hello key={idx} />
));

things.map((thing, index) => (
  <Hello key={index} />
));

things.map((thing, index, arr) => (
  <Hello key={index} />
));
Add comment

Log in to add a comment


    Be the first one to leave a comment!

Codiga Logo
Codiga Hub
  • Rulesets
  • Playground
  • Snippets
  • Cookbooks
soc-2 icon

We are SOC-2 Compliance Certified

G2 high performer medal

Codiga – All rights reserved 2022.