react: Unable to eliminate 'Each child in a list should have a unique "key" prop' warning.

Do you want to request a feature or report a bug?

Feature / Bug

What is the current behavior?

I am use Lists(Material-UI components) render nav. But ‘Each child in a list should have a unique “key” prop’ warning always appears.

image

I am pretty sure that the key attribute has been added for List and ListItem under each map, and the value is unique.

This is code:

import React from 'react';
import { List, ListItem, ListItemText } from '@material-ui/core';

const  data = [
  {
    id: '1',
    caption: 'Index',
  },
  {
    id: '2',
    caption: 'About',
  },
  ...
];

class BWKNav extends React.Component {
  render() {
    return <React.Fragment>
      <List component="nav">
         {
           data && data.length > 0 && data.map((item1, index1) => {
             return <React.Fragment>
               <ListItem key={`1${index1}`} divider={true}>
                 <ListItemText primary={item1.caption} />
               </ListItem>
               {/* Here loop secondary menu, Even if I only run the current code, this warning will still appear */}
             </React.Fragment>
         }
      </List>
    </React.Fragment>
  }
}

What is the expected behavior?

Eliminate warnings.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

latest.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 11
  • Comments: 20 (1 by maintainers)

Most upvoted comments

You have to pass the key to the React.Fragment.

the warning and stacktrace are not very helpful in locating the actual line of code that is buggy. would appreciate some more precise info that will allow me to zero in on the bug

Surprising that this is still a snag in React development coming up on the year 2022. It would save a lot of developer pain if the warning could offer some information about the elements with missing keys.

You can approximate this if you enable “Break on Warnings” in React Dev Tools and look through the stack trace around the validateChildKeys/validateExplicitKeys methods - local variables in these frames will pinpoint the offending elements.

In my case, I had a leftover fragment <>...</> surrounding one of my list items that was hard to spot in the code.

Hope someday the key needn’t added by developers.

^ like @thomasheyenbrock said, the root element in the array should have a key prop. Further, you should probably give a key based on your item’s id, or you’ll risk a bug of the list gets reordered. Rewriting your component (and removing another unnecessary Fragment) -

import React from "react";
import { List, ListItem, ListItemText } from "@material-ui/core";

const data = [
  {
    id: "1",
    caption: "Index"
  },
  {
    id: "2",
    caption: "About"
  }
  // ...
];

class BWKNav extends React.Component {
  render() {
    return (
      <List component="nav">
        {data &&
          data.length > 0 &&
          data.map((item1, index1) => {
            return (
              <React.Fragment key={item1.id}>
                <ListItem divider={true}>
                  <ListItemText primary={item1.caption} />
                </ListItem>
                {/* Here loop secondary menu, Even if I only run the current code, this warning will still appear */}
              </React.Fragment>
            );
          })}
      </List>
    );
  }
}

Don’t understand @yanlee26

I just spent far too long to find out that it wasn’t the <li> tag that was throwing the error, which already had unique key values, it was actually the parent ul tag that needed the key 🤦

I agree we need better error handling around this.

I spent far too long thinking it must be some weird bug with passing children in a HOC / wrapper for a ul and ol element.

You have to pass the key to the React.Fragment.

This didn’t work for me.

{items.map(item => (
  <React.Fragment key={item.id}>
	<TableRow>
	  <TableCell component="th" scope="row">{item.name}</TableCell>
	  <TableCell align="right">{Moment(item.createdAt).format('DD/MM/YYYY')}</TableCell>
	  <TableCell align="right">{item.active ? 'Yes' : 'No'}</TableCell>
	</TableRow>
  </React.Fragment>
))}

As and when i see this error in console. i am happy to resolve it by adding key attribute. but a simple problem is it never tells that which entity/element is missing it. i tried adding keys all over the loops and even non-loops but the error not getting off. Can you put just a simple element name which requires the key in error message?

Thanks.

I found the solution here: https://github.com/ant-design/ant-design/issues/7623#issuecomment-403331875

Every record (your rows) also need a “key”

####### I also face same problem… please help… ########

@threepointone
@shangdev

import React, {Component} from ‘react’; import {Table} from ‘react-bootstrap’;

export class Authors extends Component{

constructor(props){
    super(props);
    this.state = {deps:[]}
}

componentDidMount(){
    this.refreshList();
}
refreshList(){
    fetch('http://localhost:60039/api/authors' , 
    {credentials: 'include'}, 
    {mode:'no-cors'}, 
    {method:'GET'},
    {'Access-Control-Allow-Origin': '*'}
    )
    .then(response => response.json())
    .then(data => {
        this.setState({deps:data});
    }
    );
}



render(){
    const {deps} = this.state;
    return(          
      <Table striped bordered hover variant="dark">
          <tbody>
                {deps.map((a)=> 
                  <React.Fragment key={a.AuthorId}>    
                    <tr> 
                        <td>{a.AuthorId}</td>
                        <td>{a.FirstName}</td>
                        <td>{a.LastName}</td>
                    </tr>  
                  </React.Fragment>     
               )}
          </tbody>
      </Table>
    )
}

}

I believe adding the key to React.Fragment is not a full-proof solution even if it works. This is because it will not list the applied key in the React Developer Tools. There should be a mechanism where the Developer can see from the Dev Tool itself as what key is passed which can be seen when it is passed through a custom React Component.

Every item of vocabList needs to have a “key” prop as well. See my comment above.