next.js 列表中的每个子元素都应该有一个唯一的“键”属性自定义组件的错误

dkqlctbz  于 2023-06-05  发布在  其他
关注(0)|答案(2)|浏览(98)

我正在Map一个数组,并为数组中的每个索引呈现一个自定义的卡片组件。但是,我收到错误“列表中的每个孩子都应该有一个唯一的”键“prop”1。尽管如此,我还是将索引作为键传递。我尝试过使用React.fragment,将索引传递给card组件,并在那里添加密钥。这两个方法仍然抛出相同的错误。

主组件

import React from "react";
import { useRouter } from "next/router";
import { Button, Container } from "@mui/material";
import { makeStyles } from "@mui/styles";
import { InstructionsCard } from "../layout/directory";
import {
  RiNumber1 as OneIcon,
  RiNumber2 as TwoIcon,
  RiNumber3 as ThreeIcon,
} from "react-icons/ri";

function InstructionSection() {
  const router = useRouter();
  const classes = useStyles();

  const instructions = [
    {
      id: 1,
      icon: OneIcon,
      title: "step one",
      text: [
        "Navigate to the",
        <Button
          onClick={() => router.push("/requirements")}
          size="small"
          style={{ margin: "5px" }}
          variant="outlined"
          color="inherit"
        >
          requirements
        </Button>,
        "page for our most frequently asked questions and specific requirements before booking any activity. ",
      ],
    },
    {
      id: 2,
      icon: TwoIcon,
      title: "step two",
      text: [
        "Find the activity you are interested in and read through the information carefully. Be sure to fully understand the,",
        <Button
          onClick={() => router.push("/#upgrades")}
          size="small"
          style={{ margin: "5px" }}
          variant="outlined"
          color="inherit"
        >
          entry fee
        </Button>,
        " and",
        <Button
          onClick={() => router.push("/#upgrades")}
          size="small"
          style={{ margin: "5px" }}
          variant="outlined"
          color="inherit"
        >
          upgrade
        </Button>,
        " packages",
      ],
    },
    {
      id: 3,
      icon: ThreeIcon,
      title: "step three",
      text: [
        "Please, be sure to verify we are ",
        <Button
          onClick={() => router.push("/locations")}
          size="small"
          style={{ margin: "5px" }}
          variant="outlined"
          color="inherit"
        >
          located
        </Button>,
        " in your area. Select an experience, date, time-slot, toggle any upgrades, and continue through checkout.",
      ],
    },
  ];

  return (
    <Container className={classes.root}>
      {/* instructions iteration */}
      {instructions.map((_instruction, index) => {
        return (
          <React.Fragment key={index}>
            <InstructionsCard item={_instruction} />
          </React.Fragment>
        );
      })}
    </Container>
  );
}

// custom styles
const useStyles = makeStyles((theme) => ({
  root: {
    [theme.breakpoints.down("md")]: {
      flexDirection: "column",
    },
    width: "100%",
    display: "flex",
    justifyContent: "space-evenly",
  },
}));

export default InstructionSection;

卡片组件

import { makeStyles } from "@mui/styles";
import { Card, CardContent, Typography, Divider } from "@mui/material";

const InstructionsCard = ({ item }) => {
  const classes = useStyles();
  const Icon = item.icon;

  return (
    <Card className={classes.root}>
      <CardContent>
        <Icon className={classes.icon} />
        <Typography className={classes.title} variant="h5" component="h6">
          {item.title.toUpperCase()}
        </Typography>
        <Divider className={classes.divider} />
        <Typography
          variant="subtitle1"
          component="p"
          sx={{ mb: 1.5 }}
          color="text.secondary"
        >
          {item.text}
        </Typography>
      </CardContent>
    </Card>
  );
};

const useStyles = makeStyles((theme) => ({
  root: {
    [theme.breakpoints.down("md")]: {
      margin: theme.spacing(4, 0, 4, 0),
    },
    background: theme.palette.primary.main,
    borderRadius: theme.spacing(5),
    padding: theme.spacing(2),
    margin: theme.spacing(5),
    width: "100%",
    textAlign: "center",
    boxShadow: `0px 0px 10px 10px ${theme.palette.offset.main}`,
  },
  icon: {
    background: theme.palette.secondary.dark,
    width: "50px",
    height: "50px",
    padding: "15px",
    borderRadius: theme.spacing(5),
  },
  divider: {
    background: theme.palette.secondary.dark,
    padding: "2px",
    width: "20%",
    margin: theme.spacing(1, "auto", 1, "auto"),
  },
  title: {
    fontWeight: 800,
  },
}));

export default InstructionsCard;
ffscu2ro

ffscu2ro1#

在你的主组件中像这样改变
React.Fragment我们需要使用一次它不能使用多次

return (
    <Container className={classes.root}>
      <React.Fragment>
        {instructions.map((_instruction, index) => {
          <InstructionsCard key={index} item={_instruction} />;
        })}
      </React.Fragment>
    </Container>
  );

谢谢你

cld4siwp

cld4siwp2#

试试这个

主组件

您应该为每个子元素以及子元素中的每个元素添加一个

return (
    <Container className={classes.root}>
        {instructions.map((_instruction, index) => (
            <InstructionsCard key={_instruction.id} item={_instruction} />;
        ))}
    </Container>
);

卡片组件

添加item.id作为密钥

return (
<Card key={item.id} className={classes.root}>
  <CardContent>
    <Icon className={classes.icon} />
    <Typography className={classes.title} variant="h5" component="h6">
      {item.title.toUpperCase()}
    </Typography>
    <Divider className={classes.divider} />
    <Typography
      variant="subtitle1"
      component="p"
      sx={{ mb: 1.5 }}
      color="text.secondary"
    >
      {item.text}
    </Typography>
  </CardContent>
</Card>

);

相关问题