skip to Main Content

I have a react application (served by Next.js) in which I have multiple components on the page, each with many nested components. For two mid-level components I see the following error in the browser’s console:

Warning: Each child in a list should have a unique "key" prop.   <filename / line number>

The cause of this error and its solution are clear from the error message itself, and also well described at the linked resource (react docs). However, I don’t appear to be able to resolve them, and I’m wondering why.

The code at the given location is as follows (The line number in the error message indicates the opening "<div" line):

    return (
        <div key="messages" className={styles.comms_packet_listing}>
            {rows}
        </div>
    );

This component is a singleton – the only child within its parent component. It includes a key, which regardless of value surely satisifies the "unique among siblings" condition.

The content of the "rows" array comprises multiple "CommsPacket" components, which have a return statement as follows:

    return (
        <div key={packetSummary.packet_index} className={line_item_class}>
            My key is: {packetSummary.packet_index}<br/>
        </div>
    ); 

Each of these rows has a unique key. Since react drops those "key=" attributes from the generated HTML, I added the key into the rendered text of the component, so that I can be sure that they really are unique. Looking into the generated HTML in a browser I see the following:

My key is: 0
My key is: 1
My key is: 2
My key is: 3

Thus here again the keys appear to be unique amongst their siblings.

I have been through all divs within this component stack and ensured that they all have keys, and that all keys are unique amongst their siblings. Yet the same error message remains. Reloading in a browser I always get this error message, straight away.

Obviously I am missing something somewhere. But how to find out what and where? Ideally there would be some option within react (or Next.js) that would include the key attributes in the generated html – then it would be possible to double check my keys for uniqueness across all components in the application.

I found some related questions on SO – React list already using unique keys but still getting unique key missing error in dev tools console and React error with missing unique "key" prop when unique identifiers are already present, but the first refers to keys which may be nullish / undefined (seems not my case), and the latter refers to use of a map and seems not relevant.

What am I overlooking here?

Simplified Full Code

Following some initial feedback / questions I have updated my question with a simplified way to reproduce the error, removing most of my application code to focus on just the lines that cause the issue. Note: If I remove the {rows} line, then the error is no longer rendered in the console. This tells me the problem is with the integer keys in TelecommandService, not the TelecommandDirectory component:

page.tsx:

export default function TelecommandDirectory({}: {}) {
  const rows: any[] = [];
  const data: number[] = [2, 3, 5, 6];

  let i = 0;
  data.forEach((num: number) => {
      rows.push(
          <TelecommandService
              serviceDefinition={num} 
          />
      );
  });
  return (
      <div className={styles.telecommand_directory}>
          {rows}
      </div>
  );
}

function TelecommandService({
  serviceDefinition,
}: {
  serviceDefinition: number,
}) {
  return (
      <div key={serviceDefinition}>
          {serviceDefinition}
      </div>
  );
}

2

Answers


  1. You can remove this warning by adding the key prop in the rows loop where you are using the TelecommunicationService component. Actually, the React component is created there, and you can pass the key during the creation of the main component to ensure that React uses the key prop for the component. So, the updated code will be this. This is sufficient for uniquely identifying each instance of the TelecommandService component within the list. You don’t need any other change as the key prop is a special and reserved prop in React.

      rows.push(
          <TelecommandService
              key={num}  //key added here
              serviceDefinition={num} 
          />
      );
    
    Login or Signup to reply.
  2. The key prop is "local" to the template of the Component it appears in.

    In your case you define it within your TelecommandService Component, so it does not affect the parent TelecommandDirectory where you instantiate <TelecommandService>. Hence the error message: there is no longer key information where it is needed.

    You have 2 simple solutions:

    • Define the key prop and its unique value where it is needed, i.e. when you instantiate several times the same Component as siblings (typically when using a .map() loop, or .forEach()), in your case in the template of TelecommandDirectory Component, as shown in Muhammad Hassaan’s answer

    • Convert your TelecommandService into a "sub-template" function, instead of a Custom Component: call it like a function instead of as a Component (you can do so as long as it does not use Hooks):

    data.forEach((num: number) => {
        rows.push(
            // Execute as a function instead of as a Component (<TelecommandService />)
            // This makes it a sub-template, which keeps key prop information
            TelecommandService({
                serviceDefinition: num,
            })
        );
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search