skip to Main Content

I keep getting the warning: Each child in a list should have a unique "key" prop.

But i have applied a key with an index number to my element yet i don’t see it in the html via dev tools and the key is incrementing so they should be unique. I don’t understand why i still get this warning.

This is my code setup (im using react-bootstrap):

<Nav>
  {items.map((item, index) => (
    <NavLink item={item} index={index} onClick={handleClick} />
  ))}
</Nav>

My nav link element is created like this:

export default function NavLink({ item, index, onClick }: NavLinkProps) {
  let classes = `me-${navSpacing} fs-${fontSize} text-decoration-underline`;
  classes += item.active ? " active" : "";
  const Icon = item.icon;
  console.log(index);
  return (
    <Nav.Link className={classes} key={index} onClick={() => onClick(item.key)}>
      <Icon className={`me-${iconSpacing}`} />
      {item.text}
      {item.page && typeof item.page === "string" && <ExternalIcon />}
    </Nav.Link>
  );
}

My console log output shows (though its not clear to me why i see double) so it is incrementing the index value:

enter image description here

In the dev tools the html does not show a key attribute:

enter image description here

What am i misunderstanding here?

2

Answers


  1. You need to provide the key in this line:

    <NavLink item={item} index={index} onClick={handleClick} />
    

    i.e.

    <NavLink item={item} index={index} onClick={handleClick} key={index} />
    
    Login or Signup to reply.
  2. You should know 2 things.

    First is that you should pass the key prop on the first element in the map function and NOT the element in the first component, which means:

    // incorrect ❌
    
    const Item = ({ index }) => {
        return <li key={index}></li>
    }
    
    const App = () => {
        return <ul>{items.map(item => <Item index={item.index} />)}</ul>
    }
    
    // correct ✅
    
    const Item = () => {
        return <li></li>
    }
    
    const App = () => {
        return <ul>{items.map(item => <Item key={item.index} />)}</ul>
    }
    

    The 2nd thing you should know about is that it is recommended that you choose a real unique value instead of the array’s indices. The reason is that if you change the items in the array, their index won’t change and therefore the state value will be the same as before and will not be reset. but if you specify a real unique value for each item (e.g. uuid) then if you change the order of the items or completely a new array, the states of their components will be reset and clean.

    Edit: I’m sorry that I didn’t clarify enough about the reason we have the key prop. So, what actually the key prop is?

    The key prop is an identifier that tells the React who is this element. That being said when we use this prop on a component or a primitive element and change it later, the react believes that the element has been removed because its key is not in the react tree anymore. Then, as a result, it unmounts that element or component.

    Now, why do we use it in an array?
    We use it because the arrays are mostly dynamic and we often change their values. But React is not smart enough to guess when it should unmount an element. so we use the key prop as a signal: Hey, react! I changed the key of the item. As you can see the previous one doesn’t exist in the react tree anymore. So please unmount the previous one and mount the new one.

    But why we don’t use indices (mostly)?
    Imagine we have an array that has 5 items. Now, we delete the first one which is the 0 index. If we use the indices as keys, then the first component’s key will remain 0 and therefore the React won’t be informed that it was deleted, so it doesn’t unmount the first component and its states won’t be reset which will cause a problem you never want.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search