Chakra UI Modal component does not work with Array of object

Viewed 906

I have an array of object that is mapped through which return chakra's modal component, but it seems that the first child in the array is only returned. it displays the modal corrected but show only the first item in the Array.

import {
  Box,
  Button,
  Modal,
  ModalBody,
  ModalCloseButton,
  ModalContent,
  ModalFooter,
  ModalHeader,
  ModalOverlay,
  useDisclosure
} 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 () {
  const { isOpen, onOpen, onClose } = useDisclosure();
  return (
    <Box mt={5} display="flex" gridGap={3}>
      {courses.map((course, idx) => (
        <Box as="section" key={idx}>
          <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>
      ))}
    </Box>
  );
}

Codesandbox: https://codesandbox.io/s/objective-wave-woiek

1 Answers

Inspecting devtools revealed that both of your Modals were being opened on clicking either button, with the Geography modal on the top. It can be easily fixed by moving the hook to a separate component.

const IsolatedModal = ({ course }) => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  return (
    <Box as="section">
      <Button onClick={onOpen} size="sm">
        {course.courseTitle}
      </Button>
      <Modal isOpen={isOpen} onClose={onClose}>
        ...
      </Modal>
    </Box>
  );
};
export default function () {
  return (
    <Box mt={5} display="flex" gridGap={3}>
      {courses.map((course, idx) => (
        <IsolatedModal key={idx} course={course} />
      ))}
    </Box>
  );
}
Related