Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
shangdev opened this issue May 11, 2019 · 20 comments

Comments

@shangdev
Copy link

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.

@thomasheyenbrock
Copy link

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

@threepointone
Copy link
Contributor

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

@Sohan021
Copy link

Sohan021 commented Sep 13, 2019

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

}

@yanlee26
Copy link

Hope someday the key needn't added by developers.

@Sohan021
Copy link

Don't understand @yanlee26

@yncardoso
Copy link

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

@zys
Copy link

zys commented May 1, 2020

Having the same problem. Any suggestions?

@femiveys
Copy link

femiveys commented May 2, 2020

I found the solution here:
ant-design/ant-design#7623 (comment)

Every record (your rows) also need a "key"

@zys
Copy link

zys commented May 3, 2020

I believe that worked. I removed the React.Fragment and passed the "key" to the TableRow.

Thanks

@NiaLikesCode
Copy link

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

@femiveys
Copy link

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

@santhosh-john
Copy link

santhosh-john commented Sep 3, 2020

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.

@petercutting
Copy link

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

@ctsstc
Copy link

ctsstc commented Sep 20, 2021

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.

@vgjenks
Copy link

vgjenks commented Nov 15, 2021

I have this problem and adding the key to each item doesn't matter. Add to this; there's only one item! So...why would it yell at me about uniqueness?

`import React from "react";

import ContextButton from "../global/context_button";

import "./scss/experience.scss";

const Experience = props => {
let { experiences } = props;

const onEditClick = () => {
};

const experiencesList = () => {
    return experiences.map(exp => (
        <div id={exp.id}>{exp.title}</div>
    ));
};

return (
    <div className="experience-container">
        <div className="experience-body">
            <div className="experience-title">
                Experience
            </div>
            <div className="experience-content">
                {experiencesList()}
            </div>
        </div>
        <div className="experience-edit">
            <ContextButton icon="bytesize:edit" onClick={() => onEditClick()} />
        </div>
    </div>
);

};

export default Experience;`

Output:

image

@amitshahc
Copy link

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.

@mmontag
Copy link

mmontag commented Dec 5, 2021

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.

@kirkstrobeck
Copy link

In my case it was a function that used a spread for the props, so this didnt work

<div {...spreadProps()} key={id} />

this did

const { key, ...partialSpreadProps } = spreadProps();

<div {...partialSpreadProps} key={id} />

@renardbergson
Copy link

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

Thank you!

@b310L
Copy link

b310L commented Mar 10, 2024

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.

Thanks. This works for me. But if you remove the li parent, it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests