97

I am new to React, and I'm trying to output a table containing the information of users. But Eslint is keep giving me the following error:

[eslint] Missing "key" prop for element in iterator [react/jsx-key]

I am not sure if I did this properly, but I have assigned a unique ID number for each person in the user list, but not sure why the error is persistent.

So in my PeopleCard.js I have the following:

import React from "react";
import {
  Card,
  CardImg,
  CardText,
  CardBody,
  CardTitle,
  CardSubtitle,
  Button
} from "reactstrap";
import PropTypes from "prop-types";

class PeopleCard extends React.Component {
  static propTypes = {
    person: PropTypes.object,
    id: PropTypes.number,
    name: PropTypes.string,
    company: PropTypes.string,
    description: PropTypes.string
  };
  render() {
    return (
      <div>
        <Card>
          <CardImg
            top
            width="100%"
            src="https://via.placeholder.com/318x180.png"
            alt="Card image cap"
          />
          <CardBody>
            <CardTitle>{this.props.person.name}</CardTitle>
            <CardSubtitle>{this.props.person.company}</CardSubtitle>
            <CardText>{this.props.person.description}</CardText>
            <Button>Button</Button>
          </CardBody>
        </Card>
      </div>
    );
  }
}

export default PeopleCard;

And in my MainArea.js, I have the following:

import React from "react";
import { Container, Row, Col } from "reactstrap";
import PeopleCard from "./PeopleCard";

class MainArea extends React.Component {
  constructor() {
    super();
    this.state = {
      people: [
        {
          id: 1,
          name: "John",
          company: "Some Company, Inc",
          description: "Met at a party."
        },
        {
          id: 2,
          name: "Mary",
          company: "Some Company, Inc",
          description: "Met at a party."
        },
        {
          id: 3,
          name: "Jane",
          company: "Some Company, Inc",
          description: "Met at a party."
        }
      ]
    };
  }
  render() {
    let peopleCard = this.state.people.map(person => {
      return (
        <Col sm="4">
          <PeopleCard key={person.id} person={person} />
        </Col>
      );
    });
    return (
      <Container fluid>
        <Row>{peopleCard}</Row>
      </Container>
    );
  }
}

export default MainArea;

The following line is throwing the error, and I cannot figure out why:

<Col sm="4">
   <PeopleCard key={person.id} person={person} />
</Col>

How can I prevent this error from appearing?

3 Answers 3

127

You should put the key on the outer element inside the loop:

const peopleCard = this.state.people.map(person => (
  <Col key={person.id} sm="4">
    <PeopleCard person={person} />
  </Col>
));

If in some rarer cases you have two elements then you can put the key on a React.Fragment:

const peopleCard = this.state.people.map(person => (
  <React.Fragment key={person.id}>
    <Col key={person.id} sm="4">
      <PeopleCard person={person} />
    </Col>
    <SomeOtherElement />
  </React.Fragment>
));
Sign up to request clarification or add additional context in comments.

3 Comments

@538ROMEO check this post, it's short and straight to the point why it's useful: medium.com/@adhithiravi/…
@538ROMEO why would it make sense not to? React uses the key to identify the outer element so it can re-use the DOM node on updates even if it's moved. It shouldn't have to search arbitrarily deeper in your tree and guess that some key it encounters is ok and unique to use for a different part of the tree higher up
unclear and Failed .
4

It is always be the best practice to implement key when mapping elements. But sometimes it is kind of annoying to see this as an error instead of warning.

To turn the error into warning, you could add rules to your .eslintrc.cjs:

rules: {
  'react/jsx-key': [1, { checkFragmentShorthand: true }]
}

Comments

0

Sometimes it'll still give an issue if your two key/values get a match so better use it this way.

render() {
  let peopleCard = this.state.people.map((person, index) => {
    return (
      <Col sm="4" key={`${person.id}+${index}`}>
        <PeopleCard key={person.id} person={person} />
      </Col>
    );
  });
  return (
    <Container fluid>
      <Row>{peopleCard}</Row>
    </Container>
  );
}

Where no two loops will have the same id with index which can make the key/value different.

5 Comments

Unclear : You must have a key property for the HTML whom value is unique at each iteration of the loop.
yes, for that i am using person.id and index so that i can remain unique
You should not use index as key. Have look this article, which explains clearly why.
yes true but for now index is not a primary key, i am just using to patching it so there is no dependency with DOM element. It's true we shouldn't use index as key.
Keys must not change or that defeats their purpose. E.g. if the position of element person1+0 and person1+1 is swapped for some reason, React would still not know that, and might not update the list (because the keys index part of each item is changed as well to match the new order). -- You can argue this is a less likely error, but it's still a potential error (actually, I prefer errors that occur often over errors that occur rarely, so I'll find them and can fix them.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.