Each child in a list should have a unique "key", despite supplying unique keys

Advertisements

My component renders as follows:

if (!units) return '';
return (
  <div className = "learn">  
    {render(rootId)}
  </div>
);

Here is render (note recursion):

const render = (id) => {
  const unit = units[id];
  return (
    <>
    <div key={id} className={id}>{unit.title}</div>
    {/* No warning without the following line */}
    {unit.children.map(childId => render(childId))} 
    </>
  );
}

All ids are unique. To make sure, I added a className and here is the resulting html:

Thus, it seems that all divs do have a unique key. Nonetheless, I get the warning Each child in a list should have a unique "key". What am I missing?

>Solution :

React key should be on the outer-most mapped element, the React Fragment in this case.

const render = (id) => {
  const unit = units[id];
  return (
    <Fragment key={id}>
      <div className={id}>{unit.title}</div>
      {unit.children.map(childId => render(childId))} 
    </Fragment>
  );
}

If you are rendering only the div then the key could remain there.

const render = (id) => {
  const unit = units[id];
  return (
    <div key={id} className={id}>{unit.title}</div>
  );
}

To avoid mounting/remounting issues you should redefine render to be a component instead. (per @DennisVash)

const RenderUnits = ({ id }) => {
  const unit = units[id];
  return (
    <>
      <div className={id}>{unit.title}</div>
      {unit.children.map(id => (
        <RenderUnits key={id} id={id} /> // <-- React key here
      ))}
    </>
  );
};

...

if (!units) return '';
return (
  <div className = "learn">  
    <RenderUnits id={rootId} />
  </div>
);

Leave a Reply Cancel reply