修复使用 React 片段时的“唯一'key'prop”错误

IT技术 reactjs
2022-07-17 00:00:52

我不断收到“警告:列表中的每个孩子都应该有一个唯一的‘关键’props。” 控制台中的错误。经过一番检查,我发现需要为每个孩子以及孩子中的每个元素提供一个密钥。我已在地图功能的网格、链接和卡片组件中添加了键,但错误仍然存​​在。Card 组件的子组件是否也需要密钥?因为我认为我没有足够的唯一键。还是我向错误的组件添加了密钥?请帮忙。

export default function CourseCards() {
  const classes = useStyles();
  const [anchorEl, setAnchorEl] = React.useState(null);

  const handlePopoverOpen = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handlePopoverClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);

  // COURSE CARDS DATA
  const courseData = [
    {
      title: "Data Science  >",
      description: "Machine Learning bootcamp",
      price: "$236",
      rating: "",
      url: "/",
      img:
        "https://uploads.codesandbox.io/uploads/user/1/skny-12.jpg"
    },
    {
      title: "ApacheBlaBla >",
      description: "Coding and Basics",
      price: "",
      rating: "",
      url: "/",
      img:
        "https://uploads.codesandbox.io/uploads/user/2/e-7V-11.jpg"
    },
    {
      title: "temporary",
      description: "Testing",
      price: "",
      rating: "",
      url: "/",
      img:
        "https://uploads.codesandbox.io/uploads/user/42/Nmwx-16.jpg"
    },
    {
      title: "",
      description: "Great",
      price: "Free",
      rating: "",
      url: "/",
      img:
        "https://uploads.codesandbox.io/uploads/user/12/iiVp15.jpg"
    },
    {
      title: "Java >",
      description: "Engine Creating for PS4",
      price: "$20",
      rating: "",
      url: "/",
      img:
        "https://uploads.codesandbox.io/uploads/user/2/S0J2-13.jpg"
    },
    {
      title: "App Development >",
      description: " Developments Basics",
      price: "$30",
      rating: "",
      url: "/",
      img:
        "https://uploads.codesandbox.io/uploads/user/142/gV14.jpg"
    }
  ];

//MAPPING FUNCTION
  const courseCards = courseData.map((course, index) => (
    <>
      <Grid key={course.description} item xs={12} sm={4}>
        <Link key={course.title+index} to={course.url} className={classes.link}>
          <Card
            key={course.img}
            style={{
              maxWidth: 345,
              height: "100%",
              paddingBottom: 32,
              borderRadius: 0
            }}
          >
            <CardActionArea>
              <CardMedia
                style={{ height: 140 }}
                image={course.img}
                title={course.title}
              />
              <CardHeader
                action={
                  <IconButton
                    aria-label="more"
                    aria-owns={open ? "mouse-over-popover" : undefined}
                    aria-haspopup="true"
                    onMouseEnter={handlePopoverOpen}
                    onMouseLeave={handlePopoverClose}
                  >
                    <MoreVertIcon />
                  </IconButton>
                }
              />
              <CardContent>
                <Typography
                  gutterBottom
                  variant="body2"
                  color="textSecondary"
                  component="p"
                >
                  {course.title}
                </Typography>
                <Typography variant="h6" component="h2">
                  {course.description}
                </Typography>
              </CardContent>
            </CardActionArea>
            <CardActions
              style={{
                display: "flex",
                flexDirection: "row",
                justifyContent: "space-between"
              }}
            >
              <Button size="small" color="primary">
                {course.rating}
              </Button>
              <Button size="small" color="primary">
                {course.price}
              </Button>
            </CardActions>
          </Card>
        </Link>
      </Grid>

      <Popover
        id="mouse-over-popover"
        className={classes.popover}
        classes={{
          paper: classes.paper
        }}
        open={open}
        anchorEl={anchorEl}
        anchorOrigin={{
          vertical: "center",
          horizontal: "center"
        }}
        transformOrigin={{
          vertical: "center",
          horizontal: "right"
        }}
        onClose={handlePopoverClose}
        disableRestoreFocus
      >
        {/* POPOVER CARDS */}
        <CoursePopoverCards title={course.title} />
      </Popover>
    </>
  ));

  return (
    <div>
      <Container className={classes.container}>
        <Grid
          container
          direction="row"
          justify="space-around"
          alignItems="stretch"
          spacing={3}
        >
          {courseCards}
        </Grid>
        <Grid
          container
          direction="row"
          justify="center"
          className={classes.showBtnBox}
        >
          <Button
            variant="contained"
            className={classes.showBtn}
            color="primary"
            size="large"
          >
            Show All
          </Button>
        </Grid>
      </Container>
    </div>
  );
}
3个回答

您应该给keyFragment 元素,因为它包含其他所有内容,并且是数组中每个元素的最顶层节点。您可以删除子元素中的键。

<></>语法不支持键/属性,因此您应该以这种方式使用 Fragment 元素:

const courseCards = courseData.map((course, index) => (
    <React.Fragment key={//some unique value}>
      <Grid item xs={12} sm={4}>
      ...
    </React.Fragment>

不是对于Element子(列表)中的每个,您应该将键添加到列表的根元素。只需用Fragment添加键包装列表元素。

const courseCards = courseData.map((course, index) => (
    <React.Fragemnt key={course.title+index}>
      <Grid item xs={12} sm={4}>
        <Link to={course.url} className={classes.link}>
          <Card
            key={course.img}
            style={{
              maxWidth: 345,
              height: "100%",
              paddingBottom: 32,
              borderRadius: 0
            }}
          >
           // Stuff
          </Card>
        </Link>
      </Grid>

      <Popover
        id="mouse-over-popover"
        className={classes.popover}
        classes={{
          paper: classes.paper
        }}
        open={open}
        anchorEl={anchorEl}
        anchorOrigin={{
          vertical: "center",
          horizontal: "center"
        }}
        transformOrigin={{
          vertical: "center",
          horizontal: "right"
        }}
        onClose={handlePopoverClose}
        disableRestoreFocus
      >
        {/* POPOVER CARDS */}
        <CoursePopoverCards title={course.title} />
      </Popover>
    </React.Fragment>
  ));

提供的键map应该是唯一的,这样做

<Grid key={i} item xs={12} sm={4}>
  ...
</Grid>