I am using Next.js and the NextUI component library to create a pressable NextUI card, where upon clicking, will open up a NextUI modal. I have customized the card component in a myCard.js file. I have customized the desired modal component in a myModal.js file. I will be rendering the two in an index.js file where all of my other components get rendered. My current implementation has a pressable card, but when clicking on the card, the modal does not show up.
myCard.js:
const myCard = ({openModal}) =>
*** setup code ***
<Card
className={myCard}
radius="lg"
onPress={openModal}
isPressable
>
*** more code ***
myModal.js:
const myModal = ({isModalOpen, closeModal}) => {
*** setup code ***
return (
<Modal
isOpen={isModalOpen}
onClose={closeModal}
>
<ModalContent>
{(onClose) => (
<>
*** modal content ***
}
</ModalContent>
</Modal>
);
index.js
*** some other code ***
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => {
setIsModalOpen(true);
};
const closeModal = () => {
setIsModalOpen(false);
};
return (
<ListCard openModal={openModal}/>
<DetailCard
isOpen={isModalOpen}
onClose={closeModal}
/>
*** other code ***
)
My best guess is that the since my components are in separate files, the state values are not being communicated properly. (If I replace myCard with just a button, it works as expected). What is the most optimal way to get the pressable Card to function properly as a button that opens up the modal?
So basically, you want to make a Card which when clicked shows a Modal !
With respect to NextUI documentation you won't even need to use any states for handling Opening & Closing of Modal.
const { isOpen, onOpen, onOpenChange } = useDisclosure();
Look at the 1st Example : https://nextui.org/docs/components/modal#usage
They have provided a hook, which handles all this states. You just have to set them on your Card
component. Card has isPressable
prop, you pass
<Card onPress={onOpen} isPressable={true} >
useDisclosure()
hook.Below is a component I made :
PressableCard.js Import it in a page & use.
'use client'
import React from 'react'
import { Button, Card, CardBody, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, useDisclosure } from "@nextui-org/react";
const PressableCard = () => {
const { isOpen, onOpen, onOpenChange } = useDisclosure();
console.log("isOpen : ", isOpen);
return (
<>
<Card onPress={onOpen} isPressable={true} >
{/* PASS onOpen TO onPress EVENT LISTENER*/}
<CardBody>
<p>CLICK THIS CARD !!</p>
</CardBody>
</Card>
<Modal isOpen={isOpen} onOpenChange={onOpenChange} isDismissable={false}>
{/* PASS isOpen STATE FROM useDisclosure HOOK*/}
<ModalContent>
{(onClose) => (
<>
<ModalHeader >MODAL HEADER</ModalHeader>
<ModalBody>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Expedita, officiis?
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light"
onPress={onClose}>
{/* PASS onClose FUNCTION TO onPress EVENT LISTENER*/}
CLOSE
</Button>
<Button color="success" variant="light"
onPress={onClose}>
{/* PASS onClose OR ANY OTHER FUNCTION TO onPress EVENT LISTENER*/}
ACCEPT
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</>
)
}
export default PressableCard
Explaination :
'use client' because these components cannot be rendered server-side as it uses events. Remove 'use client' & read the error.
I have kept Card & Modal together, passed these states/values & functions
const { isOpen, onOpen, onOpenChange } = useDisclosure();
Card :
Made Card pressable & passed a function on its onPress event:
isPressable={true}
onPress={onOpen}
Modal :
Modal is opened/closed based on
isOpen={isOpen}
so Modal's isOpen = isOpen from useDisclosure.
Similarly, Modal's onOpenChange={onOpenChange} from useDisclosure.
useDisclosure()
, select useDisclosure()
in your code editor & press F12
it will show you what functions & values it returns.console logged isOpen
state/value, so when you click
on card you can see it change in console
.You may also read :
Modal Props : https://nextui.org/docs/components/modal#modal-props
Card Props : https://nextui.org/docs/components/card#modal-props
Server Components : https://nextjs.org/docs/app/building-your-application/rendering/server-components
Client Components : https://nextjs.org/docs/app/building-your-application/rendering/client-components
When to use Server and Client Components : https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#when-to-use-server-and-client-components
If there's anything I left out, missed out, Please leave a comment. I will edit this answer.