You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chakra UI Modal组件遍历对象数组时仅显示首个条目问题

问题原因

你当前的代码中,整个父组件仅初始化了一次useDisclosure,遍历生成的所有Modal和触发按钮都共享同一组开关状态。点击任意按钮触发onOpen后,所有遍历生成的Modal会同时处于打开状态,多个Modal层级叠加在视口上,视觉上你只能看到最上层的那一个,所以会出现永远只展示第一条内容的现象。

解决方案

方案1:抽离独立子组件(更推荐,状态拆分更清晰)

把单个课程的按钮+Modal逻辑抽成独立子组件,每个子组件内部自己维护useDisclosure状态,不同条目的开关状态完全隔离,不会互相干扰:

import { Box, Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay, useDisclosure } from "@chakra-ui/react";

// 独立课程卡片组件,内部维护自己的弹窗状态
const CourseCard = ({ course }) => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  return (
    <Box as="section">
      <Button onClick={onOpen} size="sm">
        {course.courseTitle}
      </Button>
      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>{course.courseTitle}</ModalHeader>
          <ModalCloseButton />
          <ModalBody>{course.courseContent}</ModalBody>
          <ModalFooter>
            <Button colorScheme="blue" mr={3} onClick={onClose}>
              Close
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </Box>
  )
}

const courses = [
  {
    courseTitle: "London",
    courseContent:
      "Lodon Lorem ipsum, dolor sit amet consectetur adipisicing elit. Tempore deleniti assumenda quas minus, fugiat veniam necessitatibus laborum qui similique dolor!"
  },
  {
    courseTitle: "Geography",
    courseContent:
      "Geography Lorem ipsum, dolor sit amet consectetur adipisicing elit. Tempore deleniti assumenda quas minus, fugiat veniam necessitatibus laborum qui similique dolor!"
  }
];

export default function () {
  return (
    <Box mt={5} display="flex" gridGap={3}>
      {courses.map((course, idx) => (
        <CourseCard key={idx} course={course} />
      ))}
    </Box>
  );
}

方案2:父组件维护激活索引

如果不想抽离组件,也可以在父组件存储当前打开的弹窗索引,单独控制对应Modal的显示隐藏:

import { useState } from "react";
import { Box, Button, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalOverlay } from "@chakra-ui/react";

const courses = [
  {
    courseTitle: "London",
    courseContent:
      "Lodon Lorem ipsum, dolor sit amet consectetur adipisicing elit. Tempore deleniti assumenda quas minus, fugiat veniam necessitatibus laborum qui similique dolor!"
  },
  {
    courseTitle: "Geography",
    courseContent:
      "Geography Lorem ipsum, dolor sit amet consectetur adipisicing elit. Tempore deleniti assumenda quas minus, fugiat veniam necessitatibus laborum qui similique dolor!"
  }
];

export default function () {
  // null代表所有弹窗关闭,存储数值对应打开的课程索引
  const [openIdx, setOpenIdx] = useState(null);
  const onClose = () => setOpenIdx(null);

  return (
    <Box mt={5} display="flex" gridGap={3}>
      {courses.map((course, idx) => (
        <Box as="section" key={idx}>
          <Button onClick={() => setOpenIdx(idx)} size="sm">
            {course.courseTitle}
          </Button>

          <Modal isOpen={openIdx === idx} onClose={onClose}>
            <ModalOverlay />
            <ModalContent>
              <ModalHeader>{course.courseTitle}</ModalHeader>
              <ModalCloseButton />
              <ModalBody>{course.courseContent}</ModalBody>
              <ModalFooter>
                <Button colorScheme="blue" mr={3} onClick={onClose}>
                  Close
                </Button>
              </ModalFooter>
            </ModalContent>
          </Modal>
        </Box>
      ))}
    </Box>
  );
}

内容的提问来源于stack exchange,提问作者AbdulAzeez Olanrewaju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 21:06:06