Chakra UI using multiple models in a single component

Viewed 8947

I am using Chakra UI and I want to use two modals in a single component.

const { isOpen , onOpen, onClose } = useDisclosure()

 <Button colorScheme="teal" size="xs" mr='2' onClick={onOpen} >
                        Edit
                    </Button>
                    {/* Edit modal */}
                    <Modal isOpen={isOpen} onClose={onClose}>
                            <ModalOverlay />
                            <ModalContent>
                            <ModalHeader>Edit Modal</ModalHeader>
                            <ModalCloseButton />
                            <ModalBody>
                               Edit Modal
                            </ModalBody>

                            <ModalFooter>
                            <Button variant="ghost" mr={3} onClick={onClose}>Cancel</Button>
                                <Button colorScheme="red" onClick={()=>{deleteAddress(address.id)}}>
                                    Delete
                                </Button>
                                
                            </ModalFooter>
                            </ModalContent>
                        </Modal>


                    {/* Delete Address */}

                    <Button colorScheme="red" size="xs"  onClick={onOpen}>
                        Delete
                    </Button> 
                    <Modal isOpen={isOpen} onClose={onClose}>
                            <ModalOverlay />
                            <ModalContent>
                            <ModalHeader>Delete Shipping Address</ModalHeader>
                            <ModalCloseButton />
                            <ModalBody>
                                Are you sure you want to delete the shipping address?
                            </ModalBody>

                            <ModalFooter>
                            <Button variant="ghost" mr={3} onClick={onClose}>Cancel</Button>
                                <Button colorScheme="red" onClick={()=>{deleteAddress(address.id)}}>
                                    Delete
                                </Button>
                                
                            </ModalFooter>
                            </ModalContent>
                        </Modal>

isOpen, onOpen and onClose can't be changed as variables since they are inbuilt Chakra functions.

Can someone suggest me a method to variate two of these modal (Chakra UI) operations?

4 Answers

You can simply change the name of variables isOpen, onOpen and onClose lets go:

const { isOpen: isEditOpen , onOpen: onEditOpen, onClose: onEditClose } = useDisclosure()
const { isOpen: isDeleteOpen , onOpen: onDeleteOpen, onClose: onDeleteClose } = useDisclosure()

{/* Edit Button*/}
<Button colorScheme="teal" size="xs" mr='2' onClick={onEditOpen} >
    Edit
</Button>

{/* Edit Modal */}
<Modal isOpen={isEditOpen} onClose={onEditClose}>
    <ModalOverlay />
    <ModalContent>
    <ModalHeader>Edit Modal</ModalHeader>
    <ModalCloseButton />
    <ModalBody>
        Edit Modal
    </ModalBody>
    <ModalFooter>
    <Button variant="ghost" mr={3} onClick={onEditClose}>Cancel</Button>
        <Button colorScheme="red" onClick={()=>{deleteAddress(address.id)}}>
            Delete
        </Button>
    </ModalFooter>
    </ModalContent>
</Modal>


{/* Delete Button*/}
<Button colorScheme="red" size="xs"  onClick={onDeleteOpen}>
    Delete
</Button> 

{/* Delete Modal*/}
<Modal isOpen={isDeleteOpen} onClose={onSecondModalClose}>
    <ModalOverlay />
    <ModalContent>
    <ModalHeader>Delete Shipping Address</ModalHeader>
    <ModalCloseButton />
    <ModalBody>
        Are you sure you want to delete the shipping address?
    </ModalBody>
    <ModalFooter>
    <Button variant="ghost" mr={3} onClick={onDeleteClose}>Cancel</Button>
        <Button colorScheme="red" onClick={()=>{deleteAddress(address.id)}}>
            Delete
        </Button>
    </ModalFooter>
    </ModalContent>
</Modal>

One more example:

First modal:

const { isOpen: isFirstModalOpen , onOpen: onFirstModalOpen, onClose: onFirstModalClose } = useDisclosure()

Second modal:

const { isOpen: isSecondModalOpen , onOpen: onSecondModalOpen, onClose: onSecondModalClose } = useDisclosure()

Now these variables have different values so you can use new names every where!

You could create a custom modal component that uses useDisclosure. Then you can have multiple instances of this custom modal component without the modals sharing the same state:

const CustomModal = ({ showModalButtonText, modalHeader, modalBody }) => {
  const { isOpen, onOpen, onClose } = useDisclosure();
  return (
    <>
      <Button colorScheme="red" size="xs" onClick={onOpen}>
        {showModalButtonText}
      </Button>
      <Modal isOpen={isOpen} onClose={onClose}>
        <ModalOverlay />
        <ModalContent>
          <ModalHeader>{modalHeader}</ModalHeader>
          <ModalCloseButton />
          <ModalBody>{modalBody}</ModalBody>

          <ModalFooter>
            <Button variant="ghost" mr={3} onClick={onClose}>
              Cancel
            </Button>
            <Button
              colorScheme="red"
              onClick={() => {
                alert(1);
              }}
            >
              Delete
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </>
  );
};

export default function App() {
  return (
    <div className="App">
      <CustomModal
        showModalButtonText="Edit"
        modalHeader="Edit Modal"
        modalBody="Edit Modal"
      />
      <CustomModal
        showModalButtonText="Delete"
        modalHeader="Delete Shipping Address"
        modalBody="Are you sure you want to delete the shipping address?"
      />
    </div>
  );
}

This way each instance of CustomModal keeps track of its own isOpen, onOpen and onClose state.

Since in your question the only dynamic parts were the button for opening, the modal, the header text and the modal body text, I've made props so these can be set separately for each instance. If more parts need to be dynamic you can add props as needed.

I've changed some small things to the modal to make it easier to test.

you can simply create two instances of useDisclosure hook.

  const {
    isOpen: isAssociationModalOpen,
    onOpen: onOpenAssociationModal,
    onClose: onCloseAssociationModal,
  } = useDisclosure();
  const {
    isOpen: isRevocationModalOpen,
    onOpen: onOpenRevocationModal,
    onClose: onCloseRevocationModal,
  } = useDisclosure();

So basically just You can change the name of variables isOpen, onOpen and onClose or you can have two instances of useDisclosure that way you can use two or more modals in your code:

import React, { useState } from 'react'
import { data } from '../../../utils/Data/data'
import {
    Table,
    Thead,
    Tbody,
    Tfoot,
    Tr,
    Th,
    Td,
    Checkbox,
    CheckboxGroup,
    Skeleton,
    Box,
    VStack,
    Button,
    HStack,
    useDisclosure


} from '@chakra-ui/react'
import EditSiteModal from '../Modal/EditSiteModal'
import DeleteSiteModal from '../Modal/DeleteSiteModal'

const MySites = () => {
    const { isOpen: isEditOpen, onOpen: onEditOpen, onClose: onEditClose } = useDisclosure()
    const { isOpen: isDeleteOpen, onOpen: onDeleteOpen, onClose: onDeleteClose } = useDisclosure()


    return (
        <>
            <Box bgColor="white" p={10}>
                <Box bgColor="white">
                    <EditSiteModal
                        isOpen={isEditOpen}
                        onClose={onEditClose}
                    />

                    <DeleteSiteModal
                        isOpen={isDeleteOpen}
                        onClose={onDeleteClose}
                    />

                    <Table variant='simple'>
                        <Thead>
                            <Tr bg="#F9F9F9" p="2" >
                                <Th></Th>
                                <Th textTransform={'capitalize'}>Site Name</Th>
                                <Th textTransform={'capitalize'}>Admin</Th>
                                <Th textTransform={'capitalize'}>Creation date & Time</Th>
                                <Th textTransform={'capitalize'}>Actions</Th>
                            </Tr>
                        </Thead>

                        <Tbody>

                            {data &&
                                data.map((sites, index: number) => {

                                    return (
                                        <Tr key={index} cursor={"pointer"}>
                                            <Td><Checkbox></Checkbox></Td>
                                            <Td>{sites.site_name}</Td>
                                            <Td>{sites.admin}</Td>
                                            <Td>{sites.creation_date}</Td>
                                            <Td>
                                                <HStack>
                                                    <Button
                                                        type="button"
                                                        bg="transparent"
                                                        border="1px"
                                                        borderRadius="base"
                                                        borderColor="#1818183D"
                                                        width="inherit"
                                                        onClick={onDeleteOpen}
                                                        mr="8px"
                                                    >
                                                        Delete
                                                    </Button>
                                                    <Button
                                                        type="button"
                                                        bg="transparent"
                                                        border="1px"
                                                        borderRadius="base"
                                                        borderColor="#F6B319"
                                                        width="inherit"
                                                        onClick={onEditOpen}
                                                    >
                                                        Edit
                                                    </Button>
                                                </HStack>
                                            </Td>
                                        </Tr>
                                    );
                                })}
                        </Tbody>
                    </Table>
                </Box>
            </Box>
        </>
    )
}

export default MySites
Related