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

Created on 11 May 2019  路  12Comments  路  Source: facebook/react

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.

Most helpful comment

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

All 12 comments

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

^ 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>
    );
  }
}
# 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>
    )
}

}

Hope someday the key needn't added by developers.

Don't understand @yanlee26

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>
))}

Having the same problem. Any suggestions?

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 believe that worked. I removed the React.Fragment and passed the "key" to the TableRow.

Thanks

I'm having a similar issue but I have the key prop. So I'm unsure of what it's complaining about

{props.vocabList.map(vocab => ( <AccordionPanelElement key={vocab.id} isChecked={vocab.selected} name={vocab.value} /> ))}

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

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.

Was this page helpful?
0 / 5 - 0 ratings